зеркало из https://github.com/mozilla/gecko-dev.git
Fix for bug 406596 (Link/anchor elements are focused within an contentEditable element). r/sr=jst, a=beltzner.
This commit is contained in:
Родитель
f2fddd2288
Коммит
c37d1b0f6f
|
@ -3520,6 +3520,13 @@ nsEventStateManager::ShiftFocusInternal(PRBool aForward, nsIContent* aStart)
|
|||
GetDocSelectionLocation(getter_AddRefs(selectionContent), getter_AddRefs(endSelectionContent), &selectionFrame, &selectionOffset);
|
||||
if (selectionContent == rootContent) // If selection on rootContent, same as null -- we have no selection yet
|
||||
selectionFrame = nsnull;
|
||||
// Don't start from the selection if the selection is in a contentEditable
|
||||
// region.
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
|
||||
if (htmlDoc &&
|
||||
htmlDoc->GetEditingState() == nsIHTMLDocument::eContentEditable &&
|
||||
selectionContent && selectionContent->HasFlag(NODE_IS_EDITABLE))
|
||||
selectionFrame = nsnull;
|
||||
// Only use tabindex if selection is synchronized with focus
|
||||
// That way, if the user clicks in content, or does a find text that lands between focusable elements,
|
||||
// they can then tab relative to that selection
|
||||
|
|
|
@ -2589,10 +2589,11 @@ nsGenericHTMLFormElement::GetDesiredIMEState()
|
|||
}
|
||||
|
||||
PRBool
|
||||
nsGenericHTMLFrameElement::IsFocusable(PRInt32 *aTabIndex)
|
||||
nsGenericHTMLFrameElement::IsHTMLFocusable(PRBool *aIsFocusable,
|
||||
PRInt32 *aTabIndex)
|
||||
{
|
||||
if (!nsGenericHTMLElement::IsFocusable(aTabIndex)) {
|
||||
return PR_FALSE;
|
||||
if (nsGenericHTMLElement::IsHTMLFocusable(aIsFocusable, aTabIndex)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// If there is no subdocument, docshell or content viewer, it's not tabbable
|
||||
|
@ -2623,11 +2624,12 @@ nsGenericHTMLFrameElement::IsFocusable(PRInt32 *aTabIndex)
|
|||
}
|
||||
}
|
||||
|
||||
*aIsFocusable = isFocusable;
|
||||
if (!isFocusable && aTabIndex) {
|
||||
*aTabIndex = -1;
|
||||
}
|
||||
|
||||
return isFocusable;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -3121,7 +3123,7 @@ nsGenericHTMLElement::RemoveFocus(nsPresContext *aPresContext)
|
|||
}
|
||||
|
||||
PRBool
|
||||
nsGenericHTMLElement::IsFocusable(PRInt32 *aTabIndex)
|
||||
nsGenericHTMLElement::IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex)
|
||||
{
|
||||
nsIDocument *doc = GetCurrentDoc();
|
||||
if (!doc || doc->HasFlag(NODE_IS_EDITABLE)) {
|
||||
|
@ -3130,14 +3132,19 @@ nsGenericHTMLElement::IsFocusable(PRInt32 *aTabIndex)
|
|||
*aTabIndex = -1;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
*aIsFocusable = PR_FALSE;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRInt32 tabIndex = 0; // Default value for non HTML elements with -moz-user-focus
|
||||
GetTabIndex(&tabIndex);
|
||||
|
||||
PRBool disabled;
|
||||
PRBool override, disabled;
|
||||
if (IsEditableRoot()) {
|
||||
// Editable roots should always be focusable.
|
||||
override = PR_TRUE;
|
||||
|
||||
// Ignore the disabled attribute in editable contentEditable/designMode
|
||||
// roots.
|
||||
disabled = PR_FALSE;
|
||||
|
@ -3148,6 +3155,8 @@ nsGenericHTMLElement::IsFocusable(PRInt32 *aTabIndex)
|
|||
}
|
||||
}
|
||||
else {
|
||||
override = PR_FALSE;
|
||||
|
||||
// Just check for disabled attribute on all HTML elements
|
||||
disabled = HasAttr(kNameSpaceID_None, nsGkAtoms::disabled);
|
||||
if (disabled) {
|
||||
|
@ -3160,7 +3169,10 @@ nsGenericHTMLElement::IsFocusable(PRInt32 *aTabIndex)
|
|||
}
|
||||
|
||||
// If a tabindex is specified at all, or the default tabindex is 0, we're focusable
|
||||
return tabIndex >= 0 || (!disabled && HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex));
|
||||
*aIsFocusable = tabIndex >= 0 ||
|
||||
(!disabled && HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex));
|
||||
|
||||
return override;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -212,7 +212,17 @@ public:
|
|||
PRBool aNotify);
|
||||
virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
|
||||
virtual void RemoveFocus(nsPresContext *aPresContext);
|
||||
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
|
||||
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull)
|
||||
{
|
||||
PRBool isFocusable;
|
||||
IsHTMLFocusable(&isFocusable, aTabIndex);
|
||||
return isFocusable;
|
||||
}
|
||||
/**
|
||||
* Returns PR_TRUE if a subclass is not allowed to override the value returned
|
||||
* in aIsFocusable.
|
||||
*/
|
||||
virtual PRBool IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex);
|
||||
virtual void PerformAccesskey(PRBool aKeyCausesActivation,
|
||||
PRBool aIsTrustedEvent);
|
||||
|
||||
|
@ -909,7 +919,7 @@ public:
|
|||
NS_DECL_NSIFRAMELOADEROWNER
|
||||
|
||||
// nsIContent
|
||||
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
|
||||
virtual PRBool IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex);
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
PRBool aCompileEventHandlers);
|
||||
|
|
|
@ -109,7 +109,7 @@ public:
|
|||
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
|
||||
PRBool aNullParent = PR_TRUE);
|
||||
virtual void SetFocus(nsPresContext* aPresContext);
|
||||
virtual PRBool IsFocusable(PRBool *aTabIndex = nsnull);
|
||||
virtual PRBool IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex);
|
||||
|
||||
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
|
||||
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
|
||||
|
@ -250,10 +250,20 @@ nsHTMLAnchorElement::SetFocus(nsPresContext* aPresContext)
|
|||
}
|
||||
|
||||
PRBool
|
||||
nsHTMLAnchorElement::IsFocusable(PRInt32 *aTabIndex)
|
||||
nsHTMLAnchorElement::IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex)
|
||||
{
|
||||
if (!nsGenericHTMLElement::IsFocusable(aTabIndex)) {
|
||||
return PR_FALSE;
|
||||
if (nsGenericHTMLElement::IsHTMLFocusable(aIsFocusable, aTabIndex)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
if (IsEditable()) {
|
||||
if (aTabIndex) {
|
||||
*aTabIndex = -1;
|
||||
}
|
||||
|
||||
*aIsFocusable = PR_FALSE;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
|
||||
|
@ -265,6 +275,9 @@ nsHTMLAnchorElement::IsFocusable(PRInt32 *aTabIndex)
|
|||
if (aTabIndex) {
|
||||
*aTabIndex = -1;
|
||||
}
|
||||
|
||||
*aIsFocusable = PR_FALSE;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -273,7 +286,9 @@ nsHTMLAnchorElement::IsFocusable(PRInt32 *aTabIndex)
|
|||
*aTabIndex = -1;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
*aIsFocusable = PR_TRUE;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -111,7 +111,7 @@ public:
|
|||
|
||||
// nsIContent overrides...
|
||||
virtual void SetFocus(nsPresContext* aPresContext);
|
||||
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
|
||||
virtual PRBool IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex);
|
||||
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
|
||||
nsIAtom* aAttribute,
|
||||
const nsAString& aValue,
|
||||
|
@ -244,15 +244,18 @@ nsHTMLButtonElement::Click()
|
|||
}
|
||||
|
||||
PRBool
|
||||
nsHTMLButtonElement::IsFocusable(PRInt32 *aTabIndex)
|
||||
nsHTMLButtonElement::IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex)
|
||||
{
|
||||
if (!nsGenericHTMLElement::IsFocusable(aTabIndex)) {
|
||||
return PR_FALSE;
|
||||
if (nsGenericHTMLElement::IsHTMLFocusable(aIsFocusable, aTabIndex)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
if (aTabIndex && (sTabFocusModel & eTabFocus_formElementsMask) == 0) {
|
||||
*aTabIndex = -1;
|
||||
}
|
||||
return PR_TRUE;
|
||||
|
||||
*aIsFocusable = PR_TRUE;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -123,7 +123,7 @@ public:
|
|||
|
||||
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
|
||||
|
||||
PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
|
||||
PRBool IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex);
|
||||
|
||||
// SetAttr override. C++ is stupid, so have to override both
|
||||
// overloaded methods.
|
||||
|
@ -435,7 +435,7 @@ nsHTMLImageElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
|||
}
|
||||
|
||||
PRBool
|
||||
nsHTMLImageElement::IsFocusable(PRInt32 *aTabIndex)
|
||||
nsHTMLImageElement::IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex)
|
||||
{
|
||||
PRInt32 tabIndex;
|
||||
GetTabIndex(&tabIndex);
|
||||
|
@ -455,7 +455,7 @@ nsHTMLImageElement::IsFocusable(PRInt32 *aTabIndex)
|
|||
}
|
||||
// Image map is not focusable itself, but flag as tabbable
|
||||
// so that image map areas get walked into.
|
||||
return PR_FALSE;
|
||||
*aIsFocusable = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -464,7 +464,10 @@ nsHTMLImageElement::IsFocusable(PRInt32 *aTabIndex)
|
|||
*aTabIndex = (sTabFocusModel & eTabFocus_formElementsMask)? tabIndex : -1;
|
||||
}
|
||||
|
||||
return tabIndex >= 0 || HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex);
|
||||
*aIsFocusable = tabIndex >= 0 ||
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex);
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -198,7 +198,7 @@ public:
|
|||
|
||||
// nsIContent
|
||||
virtual void SetFocus(nsPresContext* aPresContext);
|
||||
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
|
||||
virtual PRBool IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex);
|
||||
|
||||
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
|
||||
nsIAtom* aAttribute,
|
||||
|
@ -2902,14 +2902,15 @@ nsHTMLInputElement::WillRemoveFromRadioGroup()
|
|||
}
|
||||
|
||||
PRBool
|
||||
nsHTMLInputElement::IsFocusable(PRInt32 *aTabIndex)
|
||||
nsHTMLInputElement::IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex)
|
||||
{
|
||||
if (!nsGenericHTMLElement::IsFocusable(aTabIndex)) {
|
||||
return PR_FALSE;
|
||||
if (nsGenericHTMLElement::IsHTMLFocusable(aIsFocusable, aTabIndex)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
if (mType == NS_FORM_INPUT_TEXT || mType == NS_FORM_INPUT_PASSWORD) {
|
||||
return PR_TRUE;
|
||||
*aIsFocusable = PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (mType == NS_FORM_INPUT_HIDDEN || mType == NS_FORM_INPUT_FILE) {
|
||||
|
@ -2917,12 +2918,14 @@ nsHTMLInputElement::IsFocusable(PRInt32 *aTabIndex)
|
|||
if (aTabIndex) {
|
||||
*aTabIndex = -1;
|
||||
}
|
||||
*aIsFocusable = PR_FALSE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (!aTabIndex) {
|
||||
// The other controls are all focusable
|
||||
return PR_TRUE;
|
||||
*aIsFocusable = PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// We need to set tabindex to -1 if we're not tabbable
|
||||
|
@ -2932,14 +2935,16 @@ nsHTMLInputElement::IsFocusable(PRInt32 *aTabIndex)
|
|||
}
|
||||
|
||||
if (mType != NS_FORM_INPUT_RADIO) {
|
||||
return PR_TRUE;
|
||||
*aIsFocusable = PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool checked;
|
||||
GetChecked(&checked);
|
||||
if (checked) {
|
||||
// Selected radio buttons are tabbable
|
||||
return PR_TRUE;
|
||||
*aIsFocusable = PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Current radio button is not selected.
|
||||
|
@ -2947,7 +2952,8 @@ nsHTMLInputElement::IsFocusable(PRInt32 *aTabIndex)
|
|||
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
||||
nsAutoString name;
|
||||
if (!container || !GetNameIfExists(name)) {
|
||||
return PR_TRUE;
|
||||
*aIsFocusable = PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> currentRadio;
|
||||
|
@ -2955,7 +2961,8 @@ nsHTMLInputElement::IsFocusable(PRInt32 *aTabIndex)
|
|||
if (currentRadio) {
|
||||
*aTabIndex = -1;
|
||||
}
|
||||
return PR_TRUE;
|
||||
*aIsFocusable = PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -80,7 +80,7 @@ public:
|
|||
nsIAtom *aPrefix, const nsAString &aValue,
|
||||
PRBool aNotify);
|
||||
|
||||
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
|
||||
virtual PRBool IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex);
|
||||
virtual PRUint32 GetDesiredIMEState();
|
||||
|
||||
// Overriden nsIFormControl methods
|
||||
|
@ -247,7 +247,7 @@ nsHTMLObjectElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom *aName,
|
|||
}
|
||||
|
||||
PRBool
|
||||
nsHTMLObjectElement::IsFocusable(PRInt32 *aTabIndex)
|
||||
nsHTMLObjectElement::IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex)
|
||||
{
|
||||
if (Type() == eType_Plugin) {
|
||||
// Has plugin content: let the plugin decide what to do in terms of
|
||||
|
@ -256,10 +256,12 @@ nsHTMLObjectElement::IsFocusable(PRInt32 *aTabIndex)
|
|||
GetTabIndex(aTabIndex);
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
*aIsFocusable = PR_TRUE;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
return nsGenericHTMLFormElement::IsFocusable(aTabIndex);
|
||||
return nsGenericHTMLFormElement::IsHTMLFocusable(aIsFocusable, aTabIndex);
|
||||
}
|
||||
|
||||
PRUint32
|
||||
|
|
|
@ -1265,15 +1265,16 @@ nsHTMLSelectElement::SetFocus(nsPresContext* aPresContext)
|
|||
}
|
||||
|
||||
PRBool
|
||||
nsHTMLSelectElement::IsFocusable(PRInt32 *aTabIndex)
|
||||
nsHTMLSelectElement::IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex)
|
||||
{
|
||||
if (!nsGenericHTMLElement::IsFocusable(aTabIndex)) {
|
||||
return PR_FALSE;
|
||||
if (nsGenericHTMLElement::IsHTMLFocusable(aIsFocusable, aTabIndex)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
if (aTabIndex && (sTabFocusModel & eTabFocus_formElementsMask) == 0) {
|
||||
*aTabIndex = -1;
|
||||
}
|
||||
return PR_TRUE;
|
||||
*aIsFocusable = PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -257,7 +257,7 @@ public:
|
|||
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
|
||||
|
||||
virtual void SetFocus(nsPresContext* aPresContext);
|
||||
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
|
||||
virtual PRBool IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex);
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
||||
PRBool aNotify);
|
||||
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
|
||||
|
|
|
@ -109,7 +109,7 @@ public:
|
|||
|
||||
NS_IMETHOD GetTabIndex(PRInt32 *aTabIndex);
|
||||
NS_IMETHOD SetTabIndex(PRInt32 aTabIndex);
|
||||
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
|
||||
virtual PRBool IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex);
|
||||
virtual PRUint32 GetDesiredIMEState();
|
||||
|
||||
virtual nsresult DoneAddingChildren(PRBool aHaveNotified);
|
||||
|
@ -292,7 +292,8 @@ nsHTMLSharedObjectElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom *aName,
|
|||
}
|
||||
|
||||
PRBool
|
||||
nsHTMLSharedObjectElement::IsFocusable(PRInt32 *aTabIndex)
|
||||
nsHTMLSharedObjectElement::IsHTMLFocusable(PRBool *aIsFocusable,
|
||||
PRInt32 *aTabIndex)
|
||||
{
|
||||
if (mNodeInfo->Equals(nsGkAtoms::embed) || Type() == eType_Plugin) {
|
||||
// Has plugin content: let the plugin decide what to do in terms of
|
||||
|
@ -304,7 +305,7 @@ nsHTMLSharedObjectElement::IsFocusable(PRInt32 *aTabIndex)
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
return nsGenericHTMLElement::IsFocusable(aTabIndex);
|
||||
return nsGenericHTMLElement::IsHTMLFocusable(aIsFocusable, aTabIndex);
|
||||
}
|
||||
|
||||
PRUint32
|
||||
|
|
|
@ -109,6 +109,8 @@ _TEST_FILES = test_bug589.html \
|
|||
test_bug408231.html \
|
||||
test_bug417760.html \
|
||||
file_bug417760.png \
|
||||
test_bug406596.html \
|
||||
test_bug421640.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=406596
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 406596</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=406596">Mozilla Bug 406596</a>
|
||||
<div id="content">
|
||||
<div id="edit" contenteditable="true">This text is editable, you can change its content <a href="#" id="a" tabindex="0">abcd</a> <input type="submit" value="abcd" id="b"></input> <img src="foo.png" id="c"></div>
|
||||
<div tabindex="0">This text is not editable but is focusable</div>
|
||||
<div tabindex="0">This text is not editable but is focusable</div>
|
||||
<a href="#" id="d" contenteditable="true">abcd</a>
|
||||
<div tabindex="0">This text is not editable but is focusable</div>
|
||||
<div tabindex="0">This text is not editable but is focusable</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Bug 406596 **/
|
||||
|
||||
function testTabbing(click, focus, selectionOffset) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var wu = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
|
||||
var elem = document.getElementById(click);
|
||||
var rect = elem.getBoundingClientRect();
|
||||
var selection = window.getSelection();
|
||||
|
||||
wu.sendMouseEvent("mousedown", rect.left + 10, rect.top + 1, 0, 1, 0);
|
||||
wu.sendMouseEvent("mousemove", rect.left + 10 + selectionOffset, rect.top + 1,
|
||||
0, 1, 0);
|
||||
wu.sendMouseEvent("mouseup", rect.left + 10 + selectionOffset, rect.top + 1,
|
||||
0, 1, 0);
|
||||
if (selectionOffset) {
|
||||
is(selection.rangeCount, 1, "there should be one range in the selection");
|
||||
var range = selection.getRangeAt(0);
|
||||
}
|
||||
var focusedElement = document.activeElement;
|
||||
is(focusedElement, document.getElementById(focus),
|
||||
"clicking should move focus to the contentEditable node");
|
||||
synthesizeKey("VK_TAB", {});
|
||||
synthesizeKey("VK_TAB", {});
|
||||
synthesizeKey("VK_TAB", { shiftKey: true });
|
||||
synthesizeKey("VK_TAB", { shiftKey: true });
|
||||
is(document.activeElement, focusedElement,
|
||||
"tab/shift-tab should move focus back to the contentEditable node");
|
||||
if (selectionOffset) {
|
||||
is(selection.rangeCount, 1,
|
||||
"there should still be one range in the selection");
|
||||
var newRange = selection.getRangeAt(0);
|
||||
is(newRange.compareBoundaryPoints(Range.START_TO_START, range), 0,
|
||||
"the selection should be the same as before the tabbing");
|
||||
is(newRange.compareBoundaryPoints(Range.END_TO_END, range), 0,
|
||||
"the selection should be the same as before the tabbing");
|
||||
}
|
||||
}
|
||||
|
||||
function test() {
|
||||
window.getSelection().removeAllRanges();
|
||||
testTabbing("edit", "edit", 0);
|
||||
testTabbing("a", "edit", 0);
|
||||
testTabbing("d", "d", 0);
|
||||
testTabbing("edit", "edit", 10);
|
||||
testTabbing("a", "edit", 10);
|
||||
testTabbing("d", "d", 10);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
setTimeout(test, 0);
|
||||
};
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,59 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=421640
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 421640</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=421640">Mozilla Bug 421640</a>
|
||||
<div id="content">
|
||||
<div id="edit" contenteditable="true">This text is editable</div>
|
||||
<div><button id="button">Test</button></div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Bug 421640 **/
|
||||
|
||||
function test(click, focus, nextFocus) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var wu = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
|
||||
var selection = window.getSelection();
|
||||
var edit = document.getElementById("edit");
|
||||
var text = edit.firstChild;
|
||||
|
||||
selection.removeAllRanges();
|
||||
|
||||
var rect = edit.getBoundingClientRect();
|
||||
wu.sendMouseEvent("mousedown", rect.left + 1, rect.top + 1, 0, 1, 0);
|
||||
wu.sendMouseEvent("mousemove", rect.right - 1, rect.top + 1, 0, 1, 0);
|
||||
wu.sendMouseEvent("mouseup", rect.right - 1, rect.top + 1, 0, 1, 0);
|
||||
|
||||
is(selection.anchorNode, text, "");
|
||||
|
||||
rect = document.getElementById("button").getBoundingClientRect();
|
||||
wu.sendMouseEvent("mousedown", rect.left + 10, rect.top + 1, 0, 1, 0);
|
||||
wu.sendMouseEvent("mouseup", rect.left + 10, rect.top + 1, 0, 1, 0);
|
||||
|
||||
is(selection.anchorNode, text, "");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
setTimeout(test, 0);
|
||||
};
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -996,7 +996,8 @@ NS_IMPL_ISUPPORTS2(nsTextEditorFocusListener, nsIDOMEventListener, nsIDOMFocusLi
|
|||
nsTextEditorFocusListener::nsTextEditorFocusListener(nsIEditor *aEditor,
|
||||
nsIPresShell *aShell)
|
||||
: mEditor(aEditor),
|
||||
mPresShell(do_GetWeakReference(aShell))
|
||||
mPresShell(do_GetWeakReference(aShell)),
|
||||
mIsFocused(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1108,6 +1109,8 @@ nsTextEditorFocusListener::Focus(nsIDOMEvent* aEvent)
|
|||
if (!IsTargetFocused(target))
|
||||
return NS_OK;
|
||||
|
||||
mIsFocused = PR_TRUE;
|
||||
|
||||
// turn on selection and caret
|
||||
if (mEditor)
|
||||
{
|
||||
|
@ -1161,7 +1164,7 @@ nsTextEditorFocusListener::Focus(nsIDOMEvent* aEvent)
|
|||
selectionPrivate->SetAncestorLimiter(editableRoot);
|
||||
}
|
||||
|
||||
if (!editableRoot) {
|
||||
if (selection && !editableRoot) {
|
||||
PRInt32 rangeCount;
|
||||
selection->GetRangeCount(&rangeCount);
|
||||
if (rangeCount == 0) {
|
||||
|
@ -1182,7 +1185,7 @@ nsTextEditorFocusListener::Blur(nsIDOMEvent* aEvent)
|
|||
{
|
||||
NS_ENSURE_ARG(aEvent);
|
||||
// turn off selection and caret
|
||||
if (mEditor)
|
||||
if (mEditor && mIsFocused)
|
||||
{
|
||||
// when imeEditor exists, call ForceCompositionEnd() to tell
|
||||
// the input focus is leaving first
|
||||
|
@ -1209,18 +1212,6 @@ nsTextEditorFocusListener::Blur(nsIDOMEvent* aEvent)
|
|||
}
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
||||
nsCOMPtr<nsISelectionController> presSelCon =
|
||||
do_QueryInterface(presShell);
|
||||
if (presSelCon == selCon && selection) {
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
aEvent->GetTarget(getter_AddRefs(target));
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(target);
|
||||
nsIDocument* doc = node ? node->GetOwnerDoc() : nsnull;
|
||||
if (doc && !doc->HasFlag(NODE_IS_EDITABLE)) {
|
||||
selection->RemoveAllRanges();
|
||||
}
|
||||
}
|
||||
|
||||
if (presShell) {
|
||||
nsCOMPtr<nsICaret> caret;
|
||||
presShell->GetCaret(getter_AddRefs(caret));
|
||||
|
@ -1250,6 +1241,9 @@ nsTextEditorFocusListener::Blur(nsIDOMEvent* aEvent)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
mIsFocused = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -264,6 +264,7 @@ public:
|
|||
protected:
|
||||
nsIEditor* mEditor; // weak reference
|
||||
nsWeakPtr mPresShell;
|
||||
PRBool mIsFocused;
|
||||
};
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче