mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 802073 - Receive input event twice from input tag type:time and type:date r=vingtetun a=blocking-basecamp
This commit is contained in:
parent
b9ac8afd08
commit
962591ca72
@ -18,6 +18,13 @@ XPCOMUtils.defineLazyServiceGetter(Services, "fm",
|
||||
"@mozilla.org/focus-manager;1",
|
||||
"nsIFocusManager");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "domWindowUtils", function () {
|
||||
return content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
});
|
||||
|
||||
const FOCUS_CHANGE_DELAY = 20;
|
||||
|
||||
let HTMLInputElement = Ci.nsIDOMHTMLInputElement;
|
||||
let HTMLTextAreaElement = Ci.nsIDOMHTMLTextAreaElement;
|
||||
let HTMLSelectElement = Ci.nsIDOMHTMLSelectElement;
|
||||
@ -28,7 +35,6 @@ let FormAssistant = {
|
||||
init: function fa_init() {
|
||||
addEventListener("focus", this, true, false);
|
||||
addEventListener("blur", this, true, false);
|
||||
addEventListener("keypress", this, true, false);
|
||||
addEventListener("resize", this, true, false);
|
||||
addMessageListener("Forms:Select:Choice", this);
|
||||
addMessageListener("Forms:Input:Value", this);
|
||||
@ -37,6 +43,10 @@ let FormAssistant = {
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
},
|
||||
|
||||
ignoredInputTypes: new Set([
|
||||
'button', 'file', 'checkbox', 'radio', 'reset', 'submit', 'image'
|
||||
]),
|
||||
|
||||
isKeyboardOpened: false,
|
||||
selectionStart: 0,
|
||||
selectionEnd: 0,
|
||||
@ -80,43 +90,24 @@ let FormAssistant = {
|
||||
|
||||
switch (evt.type) {
|
||||
case "focus":
|
||||
if (this.isKeyboardOpened)
|
||||
if (this.isIMEDisabled())
|
||||
return;
|
||||
|
||||
let ignore = {
|
||||
button: true,
|
||||
file: true,
|
||||
checkbox: true,
|
||||
radio: true,
|
||||
reset: true,
|
||||
submit: true,
|
||||
image: true
|
||||
};
|
||||
|
||||
if (target instanceof HTMLSelectElement) {
|
||||
content.setTimeout(function showIMEForSelect() {
|
||||
sendAsyncMessage("Forms:Input", getJSON(target));
|
||||
});
|
||||
this.setFocusedElement(target);
|
||||
} else if (target instanceof HTMLOptionElement &&
|
||||
target.parentNode instanceof HTMLSelectElement) {
|
||||
target = target.parentNode;
|
||||
content.setTimeout(function showIMEForSelect() {
|
||||
sendAsyncMessage("Forms:Input", getJSON(target));
|
||||
});
|
||||
this.setFocusedElement(target);
|
||||
} else if ((target instanceof HTMLInputElement && !ignore[target.type]) ||
|
||||
target instanceof HTMLTextAreaElement) {
|
||||
this.isKeyboardOpened = this.tryShowIme(target);
|
||||
this.setFocusedElement(target);
|
||||
if (target && this.isFocusableElement(target)) {
|
||||
if (this.blurTimeout) {
|
||||
this.blurTimeout = content.clearTimeout(this.blurTimeout);
|
||||
this.handleIMEStateDisabled();
|
||||
}
|
||||
this.handleIMEStateEnabled(target);
|
||||
}
|
||||
break;
|
||||
|
||||
case "blur":
|
||||
if (this.focusedElement) {
|
||||
sendAsyncMessage("Forms:Input", { "type": "blur" });
|
||||
this.setFocusedElement(null);
|
||||
this.isKeyboardOpened = false;
|
||||
this.blurTimeout = content.setTimeout(function () {
|
||||
this.blurTimeout = null;
|
||||
this.handleIMEStateDisabled();
|
||||
}.bind(this), FOCUS_CHANGE_DELAY);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -146,17 +137,6 @@ let FormAssistant = {
|
||||
this.focusedElement.scrollIntoView(false);
|
||||
}
|
||||
break;
|
||||
|
||||
case "keypress":
|
||||
if (evt.keyCode != evt.DOM_VK_ESCAPE || !this.isKeyboardOpened)
|
||||
return;
|
||||
|
||||
sendAsyncMessage("Forms:Input", { "type": "blur" });
|
||||
this.isKeyboardOpened = false;
|
||||
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
@ -213,21 +193,17 @@ let FormAssistant = {
|
||||
observe: function fa_observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "ime-enabled-state-changed":
|
||||
let isOpen = this.isKeyboardOpened;
|
||||
let shouldOpen = parseInt(data);
|
||||
if (shouldOpen && !isOpen) {
|
||||
let target = Services.fm.focusedElement;
|
||||
let target = Services.fm.focusedElement;
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
if (!target || !this.tryShowIme(target)) {
|
||||
this.setFocusedElement(null);
|
||||
return;
|
||||
} else {
|
||||
this.setFocusedElement(target);
|
||||
}
|
||||
} else if (!shouldOpen && isOpen) {
|
||||
sendAsyncMessage("Forms:Input", { "type": "blur" });
|
||||
if (shouldOpen) {
|
||||
if (!this.focusedElement && this.isFocusableElement(target))
|
||||
this.handleIMEStateEnabled(target);
|
||||
} else if (this._focusedElement == target) {
|
||||
this.handleIMEStateDisabled();
|
||||
}
|
||||
this.isKeyboardOpened = shouldOpen;
|
||||
break;
|
||||
|
||||
case "xpcom-shutdown":
|
||||
@ -239,11 +215,50 @@ let FormAssistant = {
|
||||
}
|
||||
},
|
||||
|
||||
tryShowIme: function(element) {
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
isIMEDisabled: function fa_isIMEDisabled() {
|
||||
let disabled = false;
|
||||
try {
|
||||
disabled = domWindowUtils.IMEStatus == domWindowUtils.IME_STATUS_DISABLED;
|
||||
} catch (e) {}
|
||||
|
||||
return disabled;
|
||||
},
|
||||
|
||||
handleIMEStateEnabled: function fa_handleIMEStateEnabled(target) {
|
||||
if (this.isKeyboardOpened)
|
||||
return;
|
||||
|
||||
if (target instanceof HTMLOptionElement)
|
||||
target = target.parentNode;
|
||||
|
||||
let kbOpened = this.tryShowIme(target);
|
||||
if (target instanceof HTMLInputElement ||
|
||||
target instanceof HTMLTextAreaElement)
|
||||
this.isKeyboardOpened = kbOpened;
|
||||
|
||||
this.setFocusedElement(target);
|
||||
},
|
||||
|
||||
handleIMEStateDisabled: function fa_handleIMEStateDisabled() {
|
||||
sendAsyncMessage("Forms:Input", { "type": "blur" });
|
||||
this.isKeyboardOpened = false;
|
||||
this.setFocusedElement(null);
|
||||
},
|
||||
|
||||
isFocusableElement: function fa_isFocusableElement(element) {
|
||||
if (element instanceof HTMLSelectElement ||
|
||||
element instanceof HTMLTextAreaElement)
|
||||
return true;
|
||||
|
||||
if (element instanceof HTMLOptionElement &&
|
||||
element.parentNode instanceof HTMLSelectElement)
|
||||
return true;
|
||||
|
||||
return (element instanceof HTMLInputElement &&
|
||||
!this.ignoredInputTypes.has(element.type));
|
||||
},
|
||||
|
||||
tryShowIme: function(element) {
|
||||
// FIXME/bug 729623: work around apparent bug in the IME manager
|
||||
// in gecko.
|
||||
let readonly = element.getAttribute("readonly");
|
||||
|
@ -17,6 +17,7 @@ Cu.import('resource://gre/modules/accessibility/AccessFu.jsm');
|
||||
Cu.import('resource://gre/modules/Payment.jsm');
|
||||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||
Cu.import('resource://gre/modules/UserAgentOverrides.jsm');
|
||||
Cu.import('resource://gre/modules/Keyboard.jsm');
|
||||
#ifdef MOZ_B2G_RIL
|
||||
Cu.import('resource://gre/modules/NetworkStatsService.jsm');
|
||||
#endif
|
||||
|
101
b2g/components/Keyboard.jsm
Normal file
101
b2g/components/Keyboard.jsm
Normal file
@ -0,0 +1,101 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
this.EXPORTED_SYMBOLS = ['Keyboard'];
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const kFormsFrameScript = 'chrome://browser/content/forms.js';
|
||||
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
|
||||
"@mozilla.org/parentprocessmessagemanager;1", "nsIMessageBroadcaster");
|
||||
|
||||
let Keyboard = {
|
||||
_messageManager: null,
|
||||
_messageNames: [
|
||||
'SetValue', 'RemoveFocus', 'SetSelectedOption', 'SetSelectedOptions'
|
||||
],
|
||||
|
||||
get messageManager() {
|
||||
if (this._messageManager && !Cu.isDeadWrapper(this._messageManager))
|
||||
return this._messageManager;
|
||||
|
||||
throw Error('no message manager set');
|
||||
},
|
||||
|
||||
set messageManager(mm) {
|
||||
this._messageManager = mm;
|
||||
},
|
||||
|
||||
init: function keyboardInit() {
|
||||
Services.obs.addObserver(this, 'in-process-browser-frame-shown', false);
|
||||
Services.obs.addObserver(this, 'remote-browser-frame-shown', false);
|
||||
|
||||
for (let name of this._messageNames)
|
||||
ppmm.addMessageListener('Keyboard:' + name, this);
|
||||
},
|
||||
|
||||
observe: function keyboardObserve(subject, topic, data) {
|
||||
let frameLoader = subject.QueryInterface(Ci.nsIFrameLoader);
|
||||
let mm = frameLoader.messageManager;
|
||||
mm.addMessageListener('Forms:Input', this);
|
||||
|
||||
try {
|
||||
mm.loadFrameScript(kFormsFrameScript, true);
|
||||
} catch (e) {
|
||||
dump('Error loading ' + kFormsFrameScript + ' as frame script: ' + e + '\n');
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage: function keyboardReceiveMessage(msg) {
|
||||
switch (msg.name) {
|
||||
case 'Forms:Input':
|
||||
this.handleFormsInput(msg);
|
||||
break;
|
||||
case 'Keyboard:SetValue':
|
||||
this.setValue(msg);
|
||||
break;
|
||||
case 'Keyboard:RemoveFocus':
|
||||
this.removeFocus();
|
||||
break;
|
||||
case 'Keyboard:SetSelectedOption':
|
||||
this.setSelectedOption(msg);
|
||||
break;
|
||||
case 'Keyboard:SetSelectedOptions':
|
||||
this.setSelectedOption(msg);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
handleFormsInput: function keyboardHandleFormsInput(msg) {
|
||||
this.messageManager = msg.target.QueryInterface(Ci.nsIFrameLoaderOwner)
|
||||
.frameLoader.messageManager;
|
||||
|
||||
ppmm.broadcastAsyncMessage('Keyboard:FocusChange', msg.data);
|
||||
},
|
||||
|
||||
setSelectedOption: function keyboardSetSelectedOption(msg) {
|
||||
this.messageManager.sendAsyncMessage('Forms:Select:Choice', msg.data);
|
||||
},
|
||||
|
||||
setSelectedOptions: function keyboardSetSelectedOptions(msg) {
|
||||
this.messageManager.sendAsyncMessage('Forms:Select:Choice', msg.data);
|
||||
},
|
||||
|
||||
setValue: function keyboardSetValue(msg) {
|
||||
this.messageManager.sendAsyncMessage('Forms:Input:Value', msg.data);
|
||||
},
|
||||
|
||||
removeFocus: function keyboardRemoveFocus() {
|
||||
this.messageManager.sendAsyncMessage('Forms:Select:Blur', {});
|
||||
}
|
||||
};
|
||||
|
||||
Keyboard.init();
|
@ -34,6 +34,7 @@ EXTRA_PP_COMPONENTS = \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
Keyboard.jsm \
|
||||
TelURIParser.jsm \
|
||||
$(NULL)
|
||||
|
||||
|
@ -4,15 +4,16 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const kFormsFrameScript = "chrome://browser/content/forms.js";
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/ObjectWrapper.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||
"@mozilla.org/childprocessmessagemanager;1", "nsIMessageSender");
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// MozKeyboard
|
||||
// -----------------------------------------------------------------------
|
||||
@ -36,20 +37,19 @@ MozKeyboard.prototype = {
|
||||
|
||||
init: function mozKeyboardInit(win) {
|
||||
Services.obs.addObserver(this, "inner-window-destroyed", false);
|
||||
Services.obs.addObserver(this, 'in-process-browser-frame-shown', false);
|
||||
Services.obs.addObserver(this, 'remote-browser-frame-shown', false);
|
||||
cpmm.addMessageListener('Keyboard:FocusChange', this);
|
||||
|
||||
this._window = win;
|
||||
this._utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
this.innerWindowID = this._utils.currentInnerWindowID;
|
||||
|
||||
this._focusHandler = null;
|
||||
},
|
||||
|
||||
uninit: function mozKeyboardUninit() {
|
||||
Services.obs.removeObserver(this, "inner-window-destroyed");
|
||||
this._messageManager = null;
|
||||
cpmm.removeMessageListener('Keyboard:FocusChange', this);
|
||||
|
||||
this._window = null;
|
||||
this._utils = null;
|
||||
this._focusHandler = null;
|
||||
@ -63,25 +63,25 @@ MozKeyboard.prototype = {
|
||||
},
|
||||
|
||||
setSelectedOption: function mozKeyboardSetSelectedOption(index) {
|
||||
this._messageManager.sendAsyncMessage("Forms:Select:Choice", {
|
||||
"index": index
|
||||
cpmm.sendAsyncMessage('Keyboard:SetSelectedOption', {
|
||||
'index': index
|
||||
});
|
||||
},
|
||||
|
||||
setValue: function mozKeyboardSetValue(value) {
|
||||
this._messageManager.sendAsyncMessage("Forms:Input:Value", {
|
||||
"value": value
|
||||
cpmm.sendAsyncMessage('Keyboard:SetValue', {
|
||||
'value': value
|
||||
});
|
||||
},
|
||||
|
||||
setSelectedOptions: function mozKeyboardSetSelectedOptions(indexes) {
|
||||
this._messageManager.sendAsyncMessage("Forms:Select:Choice", {
|
||||
"indexes": indexes || []
|
||||
cpmm.sendAsyncMessage('Keyboard:SetSelectedOptions', {
|
||||
'indexes': indexes
|
||||
});
|
||||
},
|
||||
|
||||
removeFocus: function mozKeyboardRemoveFocus() {
|
||||
this._messageManager.sendAsyncMessage("Forms:Select:Blur", {});
|
||||
cpmm.sendAsyncMessage('Keyboard:RemoveFocus', {});
|
||||
},
|
||||
|
||||
set onfocuschange(val) {
|
||||
@ -92,7 +92,7 @@ MozKeyboard.prototype = {
|
||||
return this._focusHandler;
|
||||
},
|
||||
|
||||
handleMessage: function mozKeyboardHandleMessage(msg) {
|
||||
receiveMessage: function mozKeyboardReceiveMessage(msg) {
|
||||
let handler = this._focusHandler;
|
||||
if (!handler || !(handler instanceof Ci.nsIDOMEventListener))
|
||||
return;
|
||||
@ -107,32 +107,9 @@ MozKeyboard.prototype = {
|
||||
},
|
||||
|
||||
observe: function mozKeyboardObserve(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "inner-window-destroyed": {
|
||||
let wId = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
if (wId == this.innerWindowID) {
|
||||
this.uninit();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'remote-browser-frame-shown':
|
||||
case 'in-process-browser-frame-shown': {
|
||||
let frameLoader = subject.QueryInterface(Ci.nsIFrameLoader);
|
||||
let mm = frameLoader.messageManager;
|
||||
mm.addMessageListener("Forms:Input", (function receiveMessage(msg) {
|
||||
// Need to save mm here so later the message can be sent back to the
|
||||
// correct app in the methods called by the value selector.
|
||||
this._messageManager = mm;
|
||||
this.handleMessage(msg);
|
||||
}).bind(this));
|
||||
try {
|
||||
mm.loadFrameScript(kFormsFrameScript, true);
|
||||
} catch (e) {
|
||||
dump('Error loading ' + kFormsFrameScript + ' as frame script: ' + e + '\n');
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
let wId = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
if (wId == this.innerWindowID)
|
||||
this.uninit();
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user