backout the previous my check-ins

This commit is contained in:
Masayuki Nakano 2010-07-22 11:11:34 +09:00
Родитель 7c6e763b21
Коммит e75f1ffb27
14 изменённых файлов: 491 добавлений и 1050 удалений

Просмотреть файл

@ -71,8 +71,8 @@ enum nsLinkState {
// IID for the nsIContent interface
#define NS_ICONTENT_IID \
{ 0x2ac19ac3, 0x1dac, 0x42dc, \
{ 0xb2, 0x43, 0x78, 0x46, 0xed, 0x6f, 0x1c, 0x89 } }
{ 0x1450010b, 0xcdca, 0x451c, \
{ 0xba, 0xdc, 0x07, 0x90, 0x89, 0x7b, 0xce, 0xb8 } }
/**
* A node of content in a document's content model. This interface
@ -928,19 +928,6 @@ public:
virtual PRBool IsEqualNode(nsINode* aOther);
/**
* If this content has independent selection, e.g., if this is input field
* or textarea, this return TRUE. Otherwise, false.
*/
PRBool HasIndependentSelection();
/**
* If the content is a part of HTML editor, this returns editing
* host content. When the content is in designMode, this returns its body
* element. Also, when the content isn't editable, this returns null.
*/
nsIContent* GetEditingHost();
protected:
/**
* Hook for implementing GetID. This is guaranteed to only be

Просмотреть файл

@ -366,7 +366,8 @@ nsINode::GetSelectionRootContent(nsIPresShell* aPresShell)
return nsnull;
}
if (static_cast<nsIContent*>(this)->HasIndependentSelection()) {
nsIFrame* frame = static_cast<nsIContent*>(this)->GetPrimaryFrame();
if (frame && frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION) {
// This node should be a descendant of input/textarea editor.
nsIContent* content = GetTextEditorRootContent();
if (content)
@ -387,9 +388,15 @@ nsINode::GetSelectionRootContent(nsIPresShell* aPresShell)
editorRoot :
GetRootForContentSubtree(static_cast<nsIContent*>(this));
}
// If the document isn't editable but this is editable, this is in
// contenteditable. Use the editing host element for selection root.
return static_cast<nsIContent*>(this)->GetEditingHost();
// If the current document is not editable, but current content is
// editable, we should assume that the child of the nearest non-editable
// ancestor is selection root.
nsIContent* content = static_cast<nsIContent*>(this);
for (nsIContent* parent = GetParent();
parent && parent->HasFlag(NODE_IS_EDITABLE);
parent = content->GetParent())
content = parent;
return content;
}
}
@ -823,13 +830,14 @@ nsIContent::GetDesiredIMEState()
if (!IsEditableInternal()) {
return IME_STATUS_DISABLE;
}
// NOTE: The content for independent editors (e.g., input[type=text],
// textarea) must override this method, so, we don't need to worry about
// that here.
nsIContent *editableAncestor = GetEditingHost();
nsIContent *editableAncestor = nsnull;
for (nsIContent* parent = GetParent();
parent && parent->HasFlag(NODE_IS_EDITABLE);
parent = parent->GetParent()) {
editableAncestor = parent;
}
// This is in another editable content, use the result of it.
if (editableAncestor && editableAncestor != this) {
if (editableAncestor) {
return editableAncestor->GetDesiredIMEState();
}
nsIDocument* doc = GetCurrentDoc();
@ -857,35 +865,6 @@ nsIContent::GetDesiredIMEState()
return state;
}
PRBool
nsIContent::HasIndependentSelection()
{
nsIFrame* frame = GetPrimaryFrame();
return (frame && frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION);
}
nsIContent*
nsIContent::GetEditingHost()
{
// If this isn't editable, return NULL.
NS_ENSURE_TRUE(HasFlag(NODE_IS_EDITABLE), nsnull);
nsIDocument* doc = GetCurrentDoc();
NS_ENSURE_TRUE(doc, nsnull);
// If this is in designMode, we should return <body>
if (doc->HasFlag(NODE_IS_EDITABLE)) {
return doc->GetBodyElement();
}
nsIContent* content = this;
for (nsIContent* parent = GetParent();
parent && parent->HasFlag(NODE_IS_EDITABLE);
parent = content->GetParent()) {
content = parent;
}
return content;
}
nsresult
nsIContent::LookupNamespaceURI(const nsAString& aNamespacePrefix,
nsAString& aNamespaceURI) const

Просмотреть файл

@ -30,12 +30,6 @@ function onLoad() {
}
function onReload() {
var iframe = window.frames[0].frameElement;
SimpleTest.waitForFocus(doTest, iframe.contentWindow);
iframe.contentDocument.body.focus();
}
function doTest() {
var bodyElement = window.frames[0].frameElement.contentDocument.body;
sendChar('S', bodyElement);
sendChar('t', bodyElement);

Просмотреть файл

@ -43,8 +43,6 @@
#include "nsIDOMDocument.h"
#include "nsIDOMHTMLElement.h"
#include "nsIDOMNSHTMLElement.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOMNSEvent.h"
#include "nsPIDOMEventTarget.h"
#include "nsIMEStateManager.h"
#include "nsFocusManager.h"
@ -5168,41 +5166,3 @@ nsEditor::HasFocus()
nsCOMPtr<nsIContent> content = fm->GetFocusedContent();
return SameCOMIdentity(content, piTarget);
}
PRBool
nsEditor::IsActiveInDOMWindow()
{
nsCOMPtr<nsPIDOMEventTarget> piTarget = GetPIDOMEventTarget();
if (!piTarget) {
return PR_FALSE;
}
nsFocusManager* fm = nsFocusManager::GetFocusManager();
NS_ENSURE_TRUE(fm, PR_FALSE);
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
nsPIDOMWindow* ourWindow = doc->GetWindow();
nsCOMPtr<nsPIDOMWindow> win;
nsIContent* content =
nsFocusManager::GetFocusedDescendant(ourWindow, PR_FALSE,
getter_AddRefs(win));
return SameCOMIdentity(content, piTarget);
}
PRBool
nsEditor::IsAcceptableInputEvent(nsIDOMEvent* aEvent)
{
// If the event is trusted, the event should always cause input.
nsCOMPtr<nsIDOMNSEvent> NSEvent = do_QueryInterface(aEvent);
NS_ENSURE_TRUE(NSEvent, PR_FALSE);
PRBool isTrusted;
nsresult rv = NSEvent->GetIsTrusted(&isTrusted);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
if (isTrusted) {
return PR_TRUE;
}
// Otherwise, we shouldn't handle any input events when we're not an active
// element of the DOM window.
return IsActiveInDOMWindow();
}

Просмотреть файл

@ -659,20 +659,9 @@ public:
IsInteractionAllowed();
}
// Whether the editor has application level focus or not.
// Whether the editor has focus or not.
virtual PRBool HasFocus();
// Whether the editor is active on the DOM window. Note that when this
// returns true but HasFocus() returns false, it means that this editor was
// focused when the DOM window was active.
virtual PRBool IsActiveInDOMWindow();
// Whether the aEvent should be handled by this editor or not. When this
// returns FALSE, The aEvent shouldn't be handled on this editor,
// i.e., The aEvent should be handled by another inner editor or ancestor
// elements.
virtual PRBool IsAcceptableInputEvent(nsIDOMEvent* aEvent);
// FindSelectionRoot() returns a selection root of this editor when aNode
// gets focus. aNode must be a content node or a document node. When the
// target isn't a part of this editor, returns NULL. If this is for

Просмотреть файл

@ -316,10 +316,6 @@ nsEditorEventListener::KeyPress(nsIDOMEvent* aKeyEvent)
{
NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
if (!mEditor->IsAcceptableInputEvent(aKeyEvent)) {
return NS_OK;
}
// DOM event handling happens in two passes, the client pass and the system
// pass. We do all of our processing in the system pass, to allow client
// handlers the opportunity to cancel events and prevent typing in the editor.
@ -487,10 +483,6 @@ nsEditorEventListener::HandleText(nsIDOMEvent* aTextEvent)
{
NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
if (!mEditor->IsAcceptableInputEvent(aTextEvent)) {
return NS_OK;
}
nsCOMPtr<nsIPrivateTextEvent> textEvent = do_QueryInterface(aTextEvent);
if (!textEvent) {
//non-ui event passed in. bad things.
@ -781,9 +773,6 @@ NS_IMETHODIMP
nsEditorEventListener::HandleStartComposition(nsIDOMEvent* aCompositionEvent)
{
NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
if (!mEditor->IsAcceptableInputEvent(aCompositionEvent)) {
return NS_OK;
}
return mEditor->BeginIMEComposition();
}
@ -791,9 +780,6 @@ NS_IMETHODIMP
nsEditorEventListener::HandleEndComposition(nsIDOMEvent* aCompositionEvent)
{
NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
if (!mEditor->IsAcceptableInputEvent(aCompositionEvent)) {
return NS_OK;
}
return mEditor->EndIMEComposition();
}

Просмотреть файл

@ -426,7 +426,10 @@ nsHTMLEditor::FindSelectionRoot(nsINode *aNode)
// For non-readonly editors we want to find the root of the editable subtree
// containing aContent.
content = content->GetEditingHost();
nsIContent *parent;
while ((parent = content->GetParent()) && parent->HasFlag(NODE_IS_EDITABLE)) {
content = parent;
}
return content.forget();
}
@ -627,6 +630,17 @@ nsHTMLEditor::HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent)
return nsEditor::HandleKeyPressEvent(aKeyEvent);
}
// Don't handle events which do not belong to us (by making sure that the
// target of the event is actually editable).
// XXX we can remove this check after bug 389372
nsCOMPtr<nsIDOMEventTarget> target;
nsresult rv = aKeyEvent->GetTarget(getter_AddRefs(target));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> targetNode = do_QueryInterface(target);
if (!IsModifiableNode(targetNode)) {
return NS_OK;
}
nsKeyEvent* nativeKeyEvent = GetNativeKeyEvent(aKeyEvent);
NS_ENSURE_TRUE(nativeKeyEvent, NS_ERROR_UNEXPECTED);
NS_ASSERTION(nativeKeyEvent->message == NS_KEY_PRESS,
@ -4186,7 +4200,8 @@ nsHTMLEditor::SelectAll()
// If the anchor content has independent selection, we never need to explicitly
// select its children.
if (anchorContent->HasIndependentSelection()) {
nsIFrame* frame = anchorContent->GetPrimaryFrame();
if (frame && frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION) {
nsCOMPtr<nsISelectionPrivate> selPriv = do_QueryInterface(selection);
NS_ENSURE_TRUE(selPriv, NS_ERROR_UNEXPECTED);
rv = selPriv->SetAncestorLimiter(nsnull);
@ -5789,49 +5804,13 @@ nsHTMLEditor::HasFocus()
// If the focused content isn't editable, or it has independent selection,
// we don't have focus.
if (!focusedContent->HasFlag(NODE_IS_EDITABLE) ||
focusedContent->HasIndependentSelection()) {
IsIndependentSelectionContent(focusedContent)) {
return PR_FALSE;
}
// If our window is focused, we're focused.
return OurWindowHasFocus();
}
PRBool
nsHTMLEditor::IsActiveInDOMWindow()
{
NS_ENSURE_TRUE(mDocWeak, PR_FALSE);
nsFocusManager* fm = nsFocusManager::GetFocusManager();
NS_ENSURE_TRUE(fm, PR_FALSE);
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
PRBool inDesignMode = doc->HasFlag(NODE_IS_EDITABLE);
// If we're in designMode, we're always active in the DOM window.
if (inDesignMode) {
return PR_TRUE;
}
nsPIDOMWindow* ourWindow = doc->GetWindow();
nsCOMPtr<nsPIDOMWindow> win;
nsIContent* content =
nsFocusManager::GetFocusedDescendant(ourWindow, PR_FALSE,
getter_AddRefs(win));
if (!content) {
return PR_FALSE;
}
// We're HTML editor for contenteditable
// If the active content isn't editable, or it has independent selection,
// we're not active).
if (!content->HasFlag(NODE_IS_EDITABLE) ||
content->HasIndependentSelection()) {
return PR_FALSE;
}
return PR_TRUE;
}
already_AddRefed<nsPIDOMEventTarget>
nsHTMLEditor::GetPIDOMEventTarget()
{
@ -5941,46 +5920,11 @@ nsHTMLEditor::OurWindowHasFocus()
}
PRBool
nsHTMLEditor::IsAcceptableInputEvent(nsIDOMEvent* aEvent)
nsHTMLEditor::IsIndependentSelectionContent(nsIContent* aContent)
{
if (!nsEditor::IsAcceptableInputEvent(aEvent)) {
return PR_FALSE;
}
NS_ENSURE_TRUE(mDocWeak, PR_FALSE);
nsCOMPtr<nsIDOMEventTarget> target;
aEvent->GetTarget(getter_AddRefs(target));
NS_ENSURE_TRUE(target, PR_FALSE);
nsCOMPtr<nsIDocument> document = do_QueryReferent(mDocWeak);
if (document->HasFlag(NODE_IS_EDITABLE)) {
// If this editor is in designMode and the event target is the document,
// the event is for this editor.
nsCOMPtr<nsIDocument> targetDocument = do_QueryInterface(target);
if (targetDocument) {
return targetDocument == document;
}
// Otherwise, check whether the event target is in this document or not.
nsCOMPtr<nsIContent> targetContent = do_QueryInterface(target);
NS_ENSURE_TRUE(targetContent, PR_FALSE);
return document == targetContent->GetCurrentDoc();
}
// If this is for contenteditable, we should check whether the target is
// editable or not.
nsCOMPtr<nsIContent> targetContent = do_QueryInterface(target);
NS_ENSURE_TRUE(targetContent, PR_FALSE);
if (!targetContent->HasFlag(NODE_IS_EDITABLE) ||
targetContent->HasIndependentSelection()) {
return PR_FALSE;
}
// Finally, check whether we're actually focused or not. When we're not
// focused, we should ignore the dispatched event by script (or something)
// because content editable element needs selection in itself for editing.
// However, when we're not focused, it's not guaranteed.
return IsActiveInDOMWindow();
NS_PRECONDITION(aContent, "aContent must not be null");
nsIFrame* frame = aContent->GetPrimaryFrame();
return (frame && (frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION));
}
NS_IMETHODIMP

Просмотреть файл

@ -149,10 +149,8 @@ public:
NS_IMETHODIMP BeginningOfDocument();
virtual nsresult HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent);
virtual PRBool HasFocus();
virtual PRBool IsActiveInDOMWindow();
virtual already_AddRefed<nsPIDOMEventTarget> GetPIDOMEventTarget();
virtual already_AddRefed<nsIContent> FindSelectionRoot(nsINode *aNode);
virtual PRBool IsAcceptableInputEvent(nsIDOMEvent* aEvent);
/* ------------ nsStubMutationObserver overrides --------- */
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
@ -453,9 +451,6 @@ protected:
PRBool ShouldReplaceRootElement();
void ResetRootElementAndEventTarget();
nsresult GetBodyElement(nsIDOMHTMLElement** aBody);
// Get the focused node of this editor.
// @return If the editor has focus, this returns the focused node.
// Otherwise, returns null.
already_AddRefed<nsINode> GetFocusedNode();
// Return TRUE if aElement is a table-related elemet and caret was set
@ -750,6 +745,9 @@ protected:
// Whether the outer window of the DOM event target has focus or not.
PRBool OurWindowHasFocus();
// Whether the content has independent selection or not. E.g., input field,
// password field and textarea element. At that time, this returns TRUE.
PRBool IsIndependentSelectionContent(nsIContent* aContent);
// Data members
protected:

Просмотреть файл

@ -61,7 +61,6 @@ _TEST_FILES = \
test_bug550434.html \
test_CF_HTML_clipboard.html \
test_contenteditable_focus.html \
test_contenteditable_text_input_handling.html \
test_htmleditor_keyevent_handling.html \
test_select_all_without_body.html \
file_select_all_without_body.html \

Просмотреть файл

@ -1,336 +0,0 @@
<html>
<head>
<title>Test for text input event handling on contenteditable editor</title>
<script type="text/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="text/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
</head>
<body>
<div id="display">
<p id="static">static content<input id="inputInStatic"><textarea id="textareaInStatic"></textarea></p>
<p id="editor"contenteditable="true">content editable<input id="inputInEditor"><textarea id="textareaInEditor"></textarea></p>
</div>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(runTests);
function runTests()
{
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var fm = Components.classes["@mozilla.org/focus-manager;1"].
getService(Components.interfaces.nsIFocusManager);
var listener = {
handleEvent: function _hv(aEvent)
{
aEvent.preventDefault(); // prevent the browser default behavior
}
};
var systemGroup =
Components.classes["@mozilla.org/eventlistenerservice;1"].
getService(Components.interfaces.nsIEventListenerService).
systemEventGroup;
window.QueryInterface(Components.interfaces.nsIDOM3EventTarget);
window.addGroupedEventListener("keypress", listener, false, systemGroup);
var staticContent = document.getElementById("static");
staticContent._defaultValue = getTextValue(staticContent);
staticContent._isFocusable = false;
staticContent._isEditable = false;
staticContent._isContentEditable = false;
staticContent._description = "non-editable p element";
var inputInStatic = document.getElementById("inputInStatic");
inputInStatic._defaultValue = getTextValue(inputInStatic);
inputInStatic._isFocusable = true;
inputInStatic._isEditable = true;
inputInStatic._isContentEditable = false;
inputInStatic._description = "input element in static content";
var textareaInStatic = document.getElementById("textareaInStatic");
textareaInStatic._defaultValue = getTextValue(textareaInStatic);
textareaInStatic._isFocusable = true;
textareaInStatic._isEditable = true;
textareaInStatic._isContentEditable = false;
textareaInStatic._description = "textarea element in static content";
var editor = document.getElementById("editor");
editor._defaultValue = getTextValue(editor);
editor._isFocusable = true;
editor._isEditable = true;
editor._isContentEditable = true;
editor._description = "contenteditable editor";
var inputInEditor = document.getElementById("inputInEditor");
inputInEditor._defaultValue = getTextValue(inputInEditor);
inputInEditor._isFocusable = true;
inputInEditor._isEditable = true;
inputInEditor._isContentEditable = false;
inputInEditor._description = "input element in contenteditable editor";
var textareaInEditor = document.getElementById("textareaInEditor");
textareaInEditor._defaultValue = getTextValue(textareaInEditor);
textareaInEditor._isFocusable = true;
textareaInEditor._isEditable = true;
textareaInEditor._isContentEditable = false;
textareaInEditor._description = "textarea element in contenteditable editor";
function getTextValue(aElement)
{
if (aElement == editor) {
var value = "";
for (var node = aElement.firstChild; node; node = node.nextSibling) {
if (node.nodeType == 3) {
value += node.data;
}
}
return value;
}
return aElement.value;
}
function testTextInput(aFocus)
{
var when = " when " +
((aFocus && aFocus._isFocusable) ? aFocus._description + " has focus" :
"nobody has focus");
function checkValue(aElement, aInsertedText)
{
if (aElement == aFocus && aElement._isEditable) {
is(getTextValue(aElement), aInsertedText + aElement._defaultValue,
aElement._description +
" wasn't edited by synthesized key events" + when);
return;
}
is(getTextValue(aElement), aElement._defaultValue,
aElement._description +
" was edited by synthesized key events" + when);
}
if (aFocus && aFocus._isFocusable) {
aFocus.focus();
is(fm.focusedElement, aFocus,
aFocus._description + " didn't get focus at preparing tests" + when);
} else {
var focusedElement = fm.focusedElement;
if (focusedElement) {
focusedElement.blur();
}
ok(!fm.focusedElement,
"Failed to blur at preparing tests" + when);
}
if (aFocus && aFocus._isFocusable) {
synthesizeKey("A", { });
synthesizeKey("B", { });
synthesizeKey("C", { });
checkValue(staticContent, "ABC");
checkValue(inputInStatic, "ABC");
checkValue(textareaInStatic, "ABC");
checkValue(editor, "ABC");
checkValue(inputInEditor, "ABC");
checkValue(textareaInEditor, "ABC");
if (aFocus._isEditable) {
synthesizeKey("VK_BACK_SPACE", { });
synthesizeKey("VK_BACK_SPACE", { });
synthesizeKey("VK_BACK_SPACE", { });
checkValue(staticContent, "");
checkValue(inputInStatic, "");
checkValue(textareaInStatic, "");
checkValue(editor, "");
checkValue(inputInEditor, "");
checkValue(textareaInEditor, "");
}
}
// When key events are fired on unfocused editor.
function testDispatchedKeyEvent(aTarget)
{
var targetDescription = " (dispatched to " + aTarget._description + ")";
function dispatchKeyEvent(aKeyCode, aChar, aTarget)
{
var keyEvent = document.createEvent("KeyEvents");
keyEvent.initKeyEvent("keypress", true, true, null, false, false,
false, false, aKeyCode,
aChar ? aChar.charCodeAt(0) : 0);
aTarget.dispatchEvent(keyEvent);
}
function checkValueForDispatchedKeyEvent(aElement, aInsertedText)
{
if (aElement == aTarget && aElement._isEditable &&
(!aElement._isContentEditable || aElement == aFocus)) {
is(getTextValue(aElement), aInsertedText + aElement._defaultValue,
aElement._description +
" wasn't edited by dispatched key events" +
when + targetDescription);
return;
}
if (aElement == aTarget) {
is(getTextValue(aElement), aElement._defaultValue,
aElement._description +
" was edited by dispatched key events" +
when + targetDescription);
return;
}
is(getTextValue(aElement), aElement._defaultValue,
aElement._description +
" was edited by key events unexpectedly" +
when + targetDescription);
}
dispatchKeyEvent(0, "A", aTarget);
dispatchKeyEvent(0, "B", aTarget);
dispatchKeyEvent(0, "C", aTarget);
checkValueForDispatchedKeyEvent(staticContent, "ABC");
checkValueForDispatchedKeyEvent(inputInStatic, "ABC");
checkValueForDispatchedKeyEvent(textareaInStatic, "ABC");
checkValueForDispatchedKeyEvent(editor, "ABC");
checkValueForDispatchedKeyEvent(inputInEditor, "ABC");
checkValueForDispatchedKeyEvent(textareaInEditor, "ABC");
const nsIDOMKeyEvent = Components.interfaces.nsIDOMKeyEvent;
dispatchKeyEvent(nsIDOMKeyEvent.DOM_VK_BACK_SPACE, 0, aTarget);
dispatchKeyEvent(nsIDOMKeyEvent.DOM_VK_BACK_SPACE, 0, aTarget);
dispatchKeyEvent(nsIDOMKeyEvent.DOM_VK_BACK_SPACE, 0, aTarget);
checkValueForDispatchedKeyEvent(staticContent, "");
checkValueForDispatchedKeyEvent(inputInStatic, "");
checkValueForDispatchedKeyEvent(textareaInStatic, "");
checkValueForDispatchedKeyEvent(editor, "");
checkValueForDispatchedKeyEvent(inputInEditor, "");
checkValueForDispatchedKeyEvent(textareaInEditor, "");
}
testDispatchedKeyEvent(staticContent);
testDispatchedKeyEvent(inputInStatic);
testDispatchedKeyEvent(textareaInStatic);
testDispatchedKeyEvent(editor);
testDispatchedKeyEvent(inputInEditor);
testDispatchedKeyEvent(textareaInEditor);
if (!aFocus._isEditable) {
return;
}
// IME
const nsIDOMWindowUtils = Components.interfaces.nsIDOMWindowUtils;
// start composition
synthesizeComposition(true);
// input first character
synthesizeText(
{ "composition":
{ "string": "\u3089",
"clauses":
[
{ "length": 1, "attr": nsIDOMWindowUtils.COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 1, "length": 0 }
});
var queryText = synthesizeQueryTextContent(0, 100);
ok(queryText, "query text event result is null" + when);
if (!queryText) {
return;
}
ok(queryText.succeeded, "query text event failed" + when);
if (!queryText.succeeded) {
return;
}
is(queryText.text, "\u3089" + aFocus._defaultValue,
"composing text is incorrect" + when);
var querySelectedText = synthesizeQuerySelectedText();
ok(querySelectedText, "query selected text event result is null" + when);
if (!querySelectedText) {
return;
}
ok(querySelectedText.succeeded, "query selected text event failed" + when);
if (!querySelectedText.succeeded) {
return;
}
is(querySelectedText.offset, 1,
"query selected text event returns wrong offset" + when);
is(querySelectedText.text, "",
"query selected text event returns wrong selected text" + when);
// commit composition
synthesizeText(
{ "composition":
{ "string": "\u3089",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 1, "length": 0 }
});
queryText = synthesizeQueryTextContent(0, 100);
ok(queryText, "query text event result is null after commit" + when);
if (!queryText) {
return;
}
ok(queryText.succeeded, "query text event failed after commit" + when);
if (!queryText.succeeded) {
return;
}
is(queryText.text, "\u3089" + aFocus._defaultValue,
"composing text is incorrect after commit" + when);
querySelectedText = synthesizeQuerySelectedText();
ok(querySelectedText,
"query selected text event result is null after commit" + when);
if (!querySelectedText) {
return;
}
ok(querySelectedText.succeeded,
"query selected text event failed after commit" + when);
if (!querySelectedText.succeeded) {
return;
}
is(querySelectedText.offset, 1,
"query selected text event returns wrong offset after commit" + when);
is(querySelectedText.text, "",
"query selected text event returns wrong selected text after commit" +
when);
// end composition
synthesizeComposition(false);
checkValue(staticContent, "\u3089");
checkValue(inputInStatic, "\u3089");
checkValue(textareaInStatic, "\u3089");
checkValue(editor, "\u3089");
checkValue(inputInEditor, "\u3089");
checkValue(textareaInEditor, "\u3089");
synthesizeKey("VK_BACK_SPACE", { });
checkValue(staticContent, "");
checkValue(inputInStatic, "");
checkValue(textareaInStatic, "");
checkValue(editor, "");
checkValue(inputInEditor, "");
checkValue(textareaInEditor, "");
}
testTextInput(inputInStatic);
testTextInput(textareaInStatic);
testTextInput(editor);
testTextInput(inputInEditor);
testTextInput(textareaInEditor);
window.removeGroupedEventListener("keypress", listener, false, systemGroup);
SimpleTest.finish();
}
</script>
</body>
</html>

Просмотреть файл

@ -7,7 +7,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=468167
<title>Test for Bug 468167</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
@ -20,35 +19,31 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=468167
/** Test for Bug 468167 **/
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(runTests);
function runTests()
{
var ta = document.getElementById("ta");
ta.focus();
is(ta.scrollTop, 0, "initially scrolled to top");
var s = "";
for (var i = 0; i < 40; ++i) {
// three characters per line
if (i < 10)
s += "0";
s += i + "\n";
}
ta.value = s;
is(ta.scrollTop, 0, "scrolled to top after adding content");
ta.scrollTop = 9999; // scroll down as far as we can
isnot(ta.scrollTop, 0, "scrolled down after scrolling down");
ta.setSelectionRange(0, 99); // 33 lines out of 40
// Send a backspace key event to delete the selection
synthesizeKey("VK_BACK_SPACE", { });
is(ta.scrollTop, 0, "scrolled to top after deleting selection");
SimpleTest.finish();
var ta = document.getElementById("ta");
is(ta.scrollTop, 0, "initially scrolled to top");
var s = "";
for (var i = 0; i < 40; ++i) {
// three characters per line
if (i < 10)
s += "0";
s += i + "\n";
}
ta.value = s;
is(ta.scrollTop, 0, "scrolled to top after adding content");
ta.scrollTop = 9999; // scroll down as far as we can
isnot(ta.scrollTop, 0, "scrolled down after scrolling down");
ta.setSelectionRange(0, 99); // 33 lines out of 40
// Send a backspace key event to delete the selection
var e = document.createEvent("KeyEvents");
e.initKeyEvent("keypress", true, true, document.defaultView,
false, false, false, false,
KeyEvent.DOM_VK_BACK_SPACE, 0);
ta.dispatchEvent(e);
is(ta.scrollTop, 0, "scrolled to top after deleting selection");
</script>
</pre>

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -41,7 +41,6 @@
#include "nscore.h"
#include <windows.h>
#define NS_NUM_OF_KEYS 50
#define VK_OEM_1 0xBA // ';:' for US
#define VK_OEM_PLUS 0xBB // '+' any country
@ -77,13 +76,13 @@ struct DeadKeyEntry;
class DeadKeyTable;
class nsVirtualKey
class VirtualKey
{
union KeyShiftState
{
struct
{
PRUnichar Chars[4];
PRUnichar Chars [4];
} Normal;
struct
{
@ -92,100 +91,86 @@ class nsVirtualKey
} DeadKey;
};
KeyShiftState mShiftStates[16];
KeyShiftState mShiftStates [16];
PRUint16 mIsDeadKey;
void SetDeadKey(PRUint8 aShiftState, PRBool aIsDeadKey)
void SetDeadKey (PRUint8 aShiftState, PRBool aIsDeadKey)
{
if (aIsDeadKey) {
if (aIsDeadKey)
mIsDeadKey |= 1 << aShiftState;
} else {
else
mIsDeadKey &= ~(1 << aShiftState);
}
}
public:
PRBool IsDeadKey(PRUint8 aShiftState) const
PRBool IsDeadKey (PRUint8 aShiftState) const
{
return (mIsDeadKey & (1 << aShiftState)) != 0;
}
void AttachDeadKeyTable(PRUint8 aShiftState,
const DeadKeyTable* aDeadKeyTable)
void AttachDeadKeyTable (PRUint8 aShiftState, const DeadKeyTable* aDeadKeyTable)
{
mShiftStates[aShiftState].DeadKey.Table = aDeadKeyTable;
mShiftStates [aShiftState].DeadKey.Table = aDeadKeyTable;
}
void SetNormalChars(PRUint8 aShiftState, const PRUnichar* aChars,
PRUint32 aNumOfChars);
void SetDeadChar(PRUint8 aShiftState, PRUnichar aDeadChar);
const DeadKeyTable* MatchingDeadKeyTable(const DeadKeyEntry* aDeadKeyArray,
PRUint32 aEntries) const;
inline PRUnichar GetCompositeChar(PRUint8 aShiftState,
PRUnichar aBaseChar) const;
PRUint32 GetNativeUniChars(PRUint8 aShiftState,
PRUnichar* aUniChars = nsnull) const;
PRUint32 GetUniChars(PRUint8 aShiftState, PRUnichar* aUniChars,
PRUint8* aFinalShiftState) const;
void SetNormalChars (PRUint8 aShiftState, const PRUnichar* aChars, PRUint32 aNumOfChars);
void SetDeadChar (PRUint8 aShiftState, PRUnichar aDeadChar);
const DeadKeyTable* MatchingDeadKeyTable (const DeadKeyEntry* aDeadKeyArray, PRUint32 aEntries) const;
inline PRUnichar GetCompositeChar (PRUint8 aShiftState, PRUnichar aBaseChar) const;
PRUint32 GetNativeUniChars (PRUint8 aShiftState, PRUnichar* aUniChars = nsnull) const;
PRUint32 GetUniChars (PRUint8 aShiftState, PRUnichar* aUniChars, PRUint8* aFinalShiftState) const;
};
class nsKeyboardLayout
class KeyboardLayout
{
struct DeadKeyTableListEntry
{
DeadKeyTableListEntry* next;
PRUint8 data[1];
PRUint8 data [1];
};
#define NUM_OF_KEYS 50
HKL mKeyboardLayout;
nsVirtualKey mVirtualKeys[NS_NUM_OF_KEYS];
VirtualKey mVirtualKeys [NUM_OF_KEYS];
DeadKeyTableListEntry* mDeadKeyTableListHead;
PRInt32 mActiveDeadKey; // -1 = no active dead-key
PRUint8 mDeadKeyShiftState;
PRInt32 mLastVirtualKeyIndex;
PRUint8 mLastShiftState;
PRUnichar mChars[5]; // Dead-key + up to 4 characters
PRUint8 mShiftStates[5];
PRUnichar mChars [5]; // Dead-key + up to 4 characters
PRUint8 mShiftStates [5];
PRUint8 mNumOfChars;
static PRUint8 GetShiftState(const PBYTE aKbdState);
static void SetShiftState(PBYTE aKbdState, PRUint8 aShiftState);
static inline PRInt32 GetKeyIndex(PRUint8 aVirtualKey);
static int CompareDeadKeyEntries(const void* aArg1, const void* aArg2,
void*);
static PRBool AddDeadKeyEntry(PRUnichar aBaseChar, PRUnichar aCompositeChar,
DeadKeyEntry* aDeadKeyArray, PRUint32 aEntries);
PRBool EnsureDeadKeyActive(PRBool aIsActive, PRUint8 aDeadKey,
const PBYTE aDeadKeyKbdState);
PRUint32 GetDeadKeyCombinations(PRUint8 aDeadKey,
const PBYTE aDeadKeyKbdState,
PRUint16 aShiftStatesWithBaseChars,
DeadKeyEntry* aDeadKeyArray,
PRUint32 aMaxEntries);
void DeactivateDeadKeyState();
const DeadKeyTable* AddDeadKeyTable(const DeadKeyEntry* aDeadKeyArray,
PRUint32 aEntries);
void ReleaseDeadKeyTables();
static PRUint8 GetShiftState (const PBYTE aKbdState);
static void SetShiftState (PBYTE aKbdState, PRUint8 aShiftState);
static inline PRInt32 GetKeyIndex (PRUint8 aVirtualKey);
static int CompareDeadKeyEntries (const void* aArg1, const void* aArg2, void* aData);
static PRBool AddDeadKeyEntry (PRUnichar aBaseChar, PRUnichar aCompositeChar, DeadKeyEntry* aDeadKeyArray, PRUint32 aEntries);
PRBool EnsureDeadKeyActive (PRBool aIsActive, PRUint8 aDeadKey, const PBYTE aDeadKeyKbdState);
PRUint32 GetDeadKeyCombinations (PRUint8 aDeadKey, const PBYTE aDeadKeyKbdState, PRUint16 aShiftStatesWithBaseChars,
DeadKeyEntry* aDeadKeyArray, PRUint32 aMaxEntries);
void DeactivateDeadKeyState ();
const DeadKeyTable* AddDeadKeyTable (const DeadKeyEntry* aDeadKeyArray, PRUint32 aEntries);
void ReleaseDeadKeyTables ();
public:
nsKeyboardLayout();
~nsKeyboardLayout();
KeyboardLayout ();
~KeyboardLayout ();
static PRBool IsPrintableCharKey(PRUint8 aVirtualKey);
static PRBool IsNumpadKey(PRUint8 aVirtualKey);
static PRBool IsPrintableCharKey (PRUint8 aVirtualKey);
static PRBool IsNumpadKey (PRUint8 aVirtualKey);
PRBool IsDeadKey() const
PRBool IsDeadKey () const
{
return (mLastVirtualKeyIndex >= 0) ?
mVirtualKeys[mLastVirtualKeyIndex].IsDeadKey(mLastShiftState) : PR_FALSE;
return (mLastVirtualKeyIndex >= 0) ? mVirtualKeys [mLastVirtualKeyIndex].IsDeadKey (mLastShiftState) : PR_FALSE;
}
void LoadLayout(HKL aLayout);
void OnKeyDown(PRUint8 aVirtualKey);
PRUint32 GetUniChars(PRUnichar* aUniChars, PRUint8* aShiftStates,
PRUint32 aMaxChars) const;
void LoadLayout (HKL aLayout);
void OnKeyDown (PRUint8 aVirtualKey);
PRUint32 GetUniChars (PRUnichar* aUniChars, PRUint8* aShiftStates, PRUint32 aMaxChars) const;
PRUint32 GetUniCharsWithShiftState(PRUint8 aVirtualKey, PRUint8 aShiftStates,
PRUnichar* aUniChars,
PRUint32 aMaxChars) const;

Просмотреть файл

@ -310,7 +310,7 @@ PRLogModuleInfo* gWindowsLog = nsnull;
#ifndef WINCE
// Kbd layout. Used throughout character processing.
static nsKeyboardLayout gKbdLayout;
static KeyboardLayout gKbdLayout;
#endif
#ifdef WINCE_WINDOWS_MOBILE
@ -6319,8 +6319,7 @@ LRESULT nsWindow::OnKeyDown(const MSG &aMsg,
#ifdef WINCE
))
#else
&& !gKbdLayout.IsDeadKey() &&
nsKeyboardLayout::IsPrintableCharKey(virtualKeyCode)))
&& !gKbdLayout.IsDeadKey() && KeyboardLayout::IsPrintableCharKey(virtualKeyCode)))
#endif
{
// Remove a possible WM_CHAR or WM_SYSCHAR messages from the message queue.
@ -6384,8 +6383,8 @@ LRESULT nsWindow::OnKeyDown(const MSG &aMsg,
}
#ifndef WINCE
else if (!aModKeyState.mIsControlDown && !aModKeyState.mIsAltDown &&
(nsKeyboardLayout::IsPrintableCharKey(virtualKeyCode) ||
nsKeyboardLayout::IsNumpadKey(virtualKeyCode)))
(KeyboardLayout::IsPrintableCharKey(virtualKeyCode) ||
KeyboardLayout::IsNumpadKey(virtualKeyCode)))
{
// If this is simple KeyDown event but next message is not WM_CHAR,
// this event may not input text, so we should ignore this event.
@ -6427,7 +6426,7 @@ LRESULT nsWindow::OnKeyDown(const MSG &aMsg,
numOfUniChars = 1;
break;
default:
if (nsKeyboardLayout::IsPrintableCharKey(virtualKeyCode)) {
if (KeyboardLayout::IsPrintableCharKey(virtualKeyCode)) {
numOfUniChars = numOfShiftStates =
gKbdLayout.GetUniChars(uniChars, shiftStates,
NS_ARRAY_LENGTH(uniChars));