зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1079728 - Ensure that the blur message is sent after removing focus. r=yxl
This commit is contained in:
Родитель
03cc975d9a
Коммит
be9563ed5b
|
@ -216,7 +216,7 @@ let FormAssistant = {
|
|||
'range'
|
||||
]),
|
||||
|
||||
isKeyboardOpened: false,
|
||||
isHandlingFocus: false,
|
||||
selectionStart: -1,
|
||||
selectionEnd: -1,
|
||||
textBeforeCursor: "",
|
||||
|
@ -304,7 +304,7 @@ let FormAssistant = {
|
|||
});
|
||||
});
|
||||
if (del && element === self.focusedElement) {
|
||||
self.hideKeyboard();
|
||||
self.unhandleFocus();
|
||||
self.selectionStart = -1;
|
||||
self.selectionEnd = -1;
|
||||
}
|
||||
|
@ -351,7 +351,7 @@ let FormAssistant = {
|
|||
if (this._editing) {
|
||||
return;
|
||||
}
|
||||
this.sendKeyboardState(this.focusedElement);
|
||||
this.sendInputState(this.focusedElement);
|
||||
},
|
||||
|
||||
handleEvent: function fa_handleEvent(evt) {
|
||||
|
@ -379,13 +379,13 @@ let FormAssistant = {
|
|||
}
|
||||
|
||||
if (isContentEditable(target)) {
|
||||
this.showKeyboard(this.getTopLevelEditable(target));
|
||||
this.handleFocus(this.getTopLevelEditable(target));
|
||||
this.updateSelection();
|
||||
break;
|
||||
}
|
||||
|
||||
if (this.isFocusableElement(target)) {
|
||||
this.showKeyboard(target);
|
||||
this.handleFocus(target);
|
||||
this.updateSelection();
|
||||
}
|
||||
break;
|
||||
|
@ -406,14 +406,14 @@ let FormAssistant = {
|
|||
|
||||
case "blur":
|
||||
if (this.focusedElement) {
|
||||
this.hideKeyboard();
|
||||
this.unhandleFocus();
|
||||
this.selectionStart = -1;
|
||||
this.selectionEnd = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case "resize":
|
||||
if (!this.isKeyboardOpened)
|
||||
if (!this.isHandlingFocus)
|
||||
return;
|
||||
|
||||
if (this.scrollIntoViewTimeout) {
|
||||
|
@ -672,7 +672,7 @@ let FormAssistant = {
|
|||
|
||||
},
|
||||
|
||||
showKeyboard: function fa_showKeyboard(target) {
|
||||
handleFocus: function fa_handleFocus(target) {
|
||||
if (this.focusedElement === target)
|
||||
return;
|
||||
|
||||
|
@ -682,18 +682,17 @@ let FormAssistant = {
|
|||
this.setFocusedElement(target);
|
||||
|
||||
let count = this._focusCounter;
|
||||
this.waitForNextTick(function fa_showKeyboardSync() {
|
||||
this.waitForNextTick(function fa_handleFocusSync() {
|
||||
if (count !== this._focusCounter) {
|
||||
return;
|
||||
}
|
||||
|
||||
let kbOpened = this.sendKeyboardState(target);
|
||||
if (this.isTextInputElement(target))
|
||||
this.isKeyboardOpened = kbOpened;
|
||||
let isHandlingFocus = this.sendInputState(target);
|
||||
this.isHandlingFocus = isHandlingFocus;
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
hideKeyboard: function fa_hideKeyboard() {
|
||||
unhandleFocus: function fa_unhandleFocus() {
|
||||
this.setFocusedElement(null);
|
||||
|
||||
let count = this._focusCounter;
|
||||
|
@ -701,13 +700,13 @@ let FormAssistant = {
|
|||
// Wait for the next tick before unset the focused element and etc.
|
||||
// If the user move from one input from another,
|
||||
// the remote process should get one Forms:Input message instead of two.
|
||||
this.waitForNextTick(function fa_hideKeyboardSync() {
|
||||
this.waitForNextTick(function fa_unhandleFocusSync() {
|
||||
if (count !== this._focusCounter ||
|
||||
!this.isKeyboardOpened) {
|
||||
!this.isHandlingFocus) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isKeyboardOpened = false;
|
||||
this.isHandlingFocus = false;
|
||||
sendAsyncMessage("Forms:Input", { "type": "blur" });
|
||||
}.bind(this));
|
||||
},
|
||||
|
@ -725,12 +724,6 @@ let FormAssistant = {
|
|||
!this.ignoredInputTypes.has(element.type));
|
||||
},
|
||||
|
||||
isTextInputElement: function fa_isTextInputElement(element) {
|
||||
return element instanceof HTMLInputElement ||
|
||||
element instanceof HTMLTextAreaElement ||
|
||||
isContentEditable(element);
|
||||
},
|
||||
|
||||
getTopLevelEditable: function fa_getTopLevelEditable(element) {
|
||||
function retrieveTopLevelEditable(element) {
|
||||
while (element && !isContentEditable(element))
|
||||
|
@ -742,7 +735,7 @@ let FormAssistant = {
|
|||
return retrieveTopLevelEditable(element) || element;
|
||||
},
|
||||
|
||||
sendKeyboardState: function(element) {
|
||||
sendInputState: function(element) {
|
||||
// FIXME/bug 729623: work around apparent bug in the IME manager
|
||||
// in gecko.
|
||||
let readonly = element.getAttribute("readonly");
|
||||
|
|
|
@ -24,3 +24,4 @@ support-files =
|
|||
[test_delete_focused_element.html]
|
||||
[test_sendkey_cancel.html]
|
||||
[test_two_inputs.html]
|
||||
[test_two_selects.html]
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1079728
|
||||
-->
|
||||
<head>
|
||||
<title>Test switching between two inputs</title>
|
||||
<script type="application/javascript;version=1.7" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript;version=1.7" src="inputmethod_common.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=1079728">Mozilla Bug 1079728</a>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.7">
|
||||
|
||||
inputmethod_setup(function() {
|
||||
runTest();
|
||||
});
|
||||
|
||||
let appFrameScript = function appFrameScript() {
|
||||
let select1 = content.document.body.firstElementChild;
|
||||
let select2 = content.document.body.children[1];
|
||||
|
||||
let i = 1;
|
||||
|
||||
select1.focus();
|
||||
|
||||
addMessageListener('test:next', function() {
|
||||
i++;
|
||||
switch (i) {
|
||||
case 2:
|
||||
select2.focus();
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
select2.blur();
|
||||
select2.focus();
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
select2.blur();
|
||||
|
||||
break;
|
||||
|
||||
case 5:
|
||||
select2.focus();
|
||||
select2.blur();
|
||||
|
||||
select1.focus();
|
||||
|
||||
break;
|
||||
|
||||
case 6:
|
||||
select1.blur();
|
||||
|
||||
break;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function runTest() {
|
||||
let im = navigator.mozInputMethod;
|
||||
|
||||
let i = 0;
|
||||
im.oninputcontextchange = function(evt) {
|
||||
var inputcontext = navigator.mozInputMethod.inputcontext;
|
||||
|
||||
i++;
|
||||
switch (i) {
|
||||
// focus on the first input receives the first input context.
|
||||
case 1:
|
||||
ok(!!inputcontext, 'Receving the first input context');
|
||||
is(inputcontext.textAfterCursor, 'First');
|
||||
|
||||
mm.sendAsyncMessage('test:next');
|
||||
break;
|
||||
|
||||
// focus on the second input (implicitly blur the first input)
|
||||
// results the second input context.
|
||||
case 2:
|
||||
ok(!!inputcontext, 'Receving the second input context');
|
||||
is(inputcontext.textAfterCursor, 'Second');
|
||||
|
||||
|
||||
mm.sendAsyncMessage('test:next');
|
||||
break;
|
||||
|
||||
// blur and re-focus on the second input results updated
|
||||
// input context for the second input.
|
||||
case 3:
|
||||
ok(!!inputcontext, 'Receving the second input context');
|
||||
is(inputcontext.textAfterCursor, 'Second');
|
||||
|
||||
mm.sendAsyncMessage('test:next');
|
||||
break;
|
||||
|
||||
// blur on the second input results null input context
|
||||
case 4:
|
||||
is(inputcontext, null, 'Receving null inputcontext');
|
||||
|
||||
mm.sendAsyncMessage('test:next');
|
||||
break;
|
||||
|
||||
// focus and blur on the second input sends no message;
|
||||
// focus on the first input receives the first input context.
|
||||
case 5:
|
||||
ok(!!inputcontext, 'Receving the first input context');
|
||||
is(inputcontext.textAfterCursor, 'First');
|
||||
|
||||
mm.sendAsyncMessage('test:next');
|
||||
break;
|
||||
|
||||
// blur on the first input results null input context
|
||||
case 6:
|
||||
is(inputcontext, null, 'Receving null inputcontext');
|
||||
|
||||
inputmethod_cleanup();
|
||||
break;
|
||||
|
||||
default:
|
||||
ok(false, 'Receving extra inputcontextchange calls');
|
||||
inputmethod_cleanup();
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// Set current page as an input method.
|
||||
SpecialPowers.wrap(im).setActive(true);
|
||||
|
||||
let iframe = document.createElement('iframe');
|
||||
iframe.src = 'data:text/html,<html><body><select><option>First</option></select><select><option>Second</option></select></html>';
|
||||
iframe.setAttribute('mozbrowser', true);
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
|
||||
|
||||
iframe.addEventListener('mozbrowserloadend', function() {
|
||||
mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
Загрузка…
Ссылка в новой задаче