From 55de3e5111c67e20cbc8de9e5894c36f542b2003 Mon Sep 17 00:00:00 2001 From: Tim Chien Date: Thu, 28 Aug 2014 23:38:00 -0400 Subject: [PATCH] Bug 1057898 - Tap between two inputs should result one inputcontextchange event. r=yxl --- dom/inputmethod/forms.js | 50 +++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/dom/inputmethod/forms.js b/dom/inputmethod/forms.js index 151b3ee731698..2573b7d280c7b 100644 --- a/dom/inputmethod/forms.js +++ b/dom/inputmethod/forms.js @@ -18,6 +18,10 @@ XPCOMUtils.defineLazyServiceGetter(Services, "fm", "@mozilla.org/focus-manager;1", "nsIFocusManager"); +XPCOMUtils.defineLazyServiceGetter(Services, "threadManager", + "@mozilla.org/thread-manager;1", + "nsIThreadManager"); + XPCOMUtils.defineLazyGetter(this, "domWindowUtils", function () { return content.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindowUtils); @@ -250,9 +254,6 @@ let FormAssistant = { this._observer.disconnect(); this._observer = null; } - if (!element) { - this.focusedElement.blur(); - } if (this._selectionPrivate) { this._selectionPrivate.removeSelectionListener(this); this._selectionPrivate = null; @@ -298,8 +299,9 @@ let FormAssistant = { }); }); if (del && element === self.focusedElement) { - // item was deleted, fake a blur so all state gets set correctly - self.handleEvent({ target: element, type: "blur" }); + self.hideKeyboard(); + self.selectionStart = -1; + self.selectionEnd = -1; } }); @@ -378,8 +380,13 @@ let FormAssistant = { break; } // fall through - case "blur": case "submit": + if (this.focusedElement) { + this.focusedElement.blur(); + } + break; + + case "blur": if (this.focusedElement) { this.hideKeyboard(); this.selectionStart = -1; @@ -434,6 +441,13 @@ let FormAssistant = { } }, + waitForNextTick: function(callback) { + var tm = Services.threadManager; + tm.mainThread.dispatch({ + run: callback, + }, Components.interfaces.nsIThread.DISPATCH_NORMAL); + }, + receiveMessage: function fa_receiveMessage(msg) { let target = this.focusedElement; let json = msg.json; @@ -536,7 +550,10 @@ let FormAssistant = { break; case "Forms:Select:Blur": { - this.setFocusedElement(null); + if (this.focusedElement) { + this.focusedElement.blur(); + } + break; } @@ -655,9 +672,20 @@ let FormAssistant = { }, hideKeyboard: function fa_hideKeyboard() { - sendAsyncMessage("Forms:Input", { "type": "blur" }); - this.isKeyboardOpened = false; - this.setFocusedElement(null); + var element = this.focusedElement; + + // 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() { + if (element !== this.focusedElement) { + return; + } + + this.isKeyboardOpened = false; + this.setFocusedElement(null); + sendAsyncMessage("Forms:Input", { "type": "blur" }); + }.bind(this)); }, isFocusableElement: function fa_isFocusableElement(element) { @@ -738,7 +766,7 @@ let FormAssistant = { // one to [0,0] and one to actual value. Both are sent in same tick. // Prevent firing two events in that scenario, always only use the last 1. // - // It is also a workaround for Bug 1053048, which prevents + // It is also a workaround for Bug 1053048, which prevents // getSelectionInfo() accessing selectionStart or selectionEnd in the // callback function of nsISelectionListener::NotifySelectionChanged(). if (this._selectionTimeout) {