Bug 1115616 - Commit composition string forcibly when search suggestion list is clicked. r=gavin,adw

This commit is contained in:
Tooru Fujisawa 2015-01-21 05:39:27 +09:00
parent 640e727632
commit dc6571e127
3 changed files with 87 additions and 0 deletions

View File

@ -57,6 +57,8 @@ function SearchSuggestionUIController(inputElement, tableParent, onClick=null,
this._stickyInputValue = "";
this._hideSuggestions();
this._ignoreInputEvent = false;
}
SearchSuggestionUIController.prototype = {
@ -143,6 +145,10 @@ SearchSuggestionUIController.prototype = {
},
_onInput: function () {
if (this._ignoreInputEvent) {
this._ignoreInputEvent = false;
return;
}
if (this.input.value) {
this._getSuggestions();
}
@ -231,6 +237,20 @@ SearchSuggestionUIController.prototype = {
let idx = this._indexOfTableRowOrDescendent(event.target);
let suggestion = this.suggestionAtIndex(idx);
this._stickyInputValue = suggestion;
// Commit composition string forcibly, because setting input value does not
// work if input has composition string (see bug 1115616 and bug 632744).
try {
let imeEditor = this.input.editor.QueryInterface(Components.interfaces.nsIEditorIMESupport);
if (imeEditor.composing) {
// Ignore input event for compisition end to avoid getting suggestion
// again.
this._ignoreInputEvent = true;
imeEditor.forceCompositionEnd();
this._ignoreInputEvent = false;
}
} catch(e) { }
this.input.value = suggestion;
this.input.setAttribute("selection-index", idx);
this.input.setAttribute("selection-kind", "mouse");

View File

@ -187,6 +187,46 @@ add_task(function* formHistory() {
yield msg("reset");
});
add_task(function* composition() {
yield setUp();
let state = yield msg("startComposition", { data: "" });
checkState(state, "", [], -1);
state = yield msg("updateComposition", { data: "x" });
checkState(state, "", [], -1);
state = yield msg("changeComposition", { data: "x", waitForSuggestions: true });
checkState(state, "x", ["xfoo", "xbar"], -1);
// Mouse over the first suggestion.
state = yield msg("mousemove", 0);
checkState(state, "x", ["xfoo", "xbar"], 0);
// Mouse over the second suggestion.
state = yield msg("mousemove", 1);
checkState(state, "x", ["xfoo", "xbar"], 1);
// Click the second suggestion. This should make it sticky. To make sure it
// sticks, trigger suggestions again and cycle through them by pressing Down
// until nothing is selected again.
state = yield msg("mousedown", 1);
checkState(state, "xbar", [], -1);
state = yield msg("key", { key: "VK_DOWN", waitForSuggestions: true });
checkState(state, "xbar", ["xbarfoo", "xbarbar"], -1);
state = yield msg("key", "VK_DOWN");
checkState(state, "xbarfoo", ["xbarfoo", "xbarbar"], 0);
state = yield msg("key", "VK_DOWN");
checkState(state, "xbarbar", ["xbarfoo", "xbarbar"], 1);
state = yield msg("key", "VK_DOWN");
checkState(state, "xbar", ["xbarfoo", "xbarbar"], -1);
yield msg("reset");
});
let gDidInitialSetUp = false;

View File

@ -27,6 +27,33 @@ let messageHandlers = {
wait(ack);
},
startComposition: function (arg) {
let data = typeof(arg) == "string" ? arg : arg.data;
content.synthesizeComposition({ type: "compositionstart", data: data });
ack();
},
updateComposition: function (arg) {
let data = typeof(arg) == "string" ? arg : arg.data;
content.synthesizeComposition({ type: "compositionupdate", data: data });
ack();
},
changeComposition: function (arg) {
let data = typeof(arg) == "string" ? arg : arg.data;
content.synthesizeCompositionChange({
composition: {
string: data,
clauses: [
{ length: data.length, attr: content.COMPOSITION_ATTR_RAWINPUT }
]
},
caret: { start: data.length, length: 0 }
});
let wait = arg.waitForSuggestions ? waitForSuggestions : cb => cb();
wait(ack);
},
focus: function () {
gController.input.focus();
ack();