mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-25 20:01:50 +00:00
Bug 1197682 - InputMethodManager#setSupportsSwitchingTypes, r=janjongboom, sr=smaug
This commit is contained in:
parent
4d5d75f626
commit
5c6b996776
@ -45,8 +45,10 @@ this.Keyboard = {
|
||||
_keyboardMM: null, // The keyboard app message manager.
|
||||
_keyboardID: -1, // The keyboard app's ID number. -1 = invalid
|
||||
_nextKeyboardID: 0, // The ID number counter.
|
||||
_systemMessageName: [
|
||||
'SetValue', 'RemoveFocus', 'SetSelectedOption', 'SetSelectedOptions'
|
||||
_supportsSwitchingTypes: [],
|
||||
_systemMessageNames: [
|
||||
'SetValue', 'RemoveFocus', 'SetSelectedOption', 'SetSelectedOptions',
|
||||
'SetSupportsSwitchingTypes'
|
||||
],
|
||||
|
||||
_messageNames: [
|
||||
@ -70,6 +72,12 @@ this.Keyboard = {
|
||||
},
|
||||
|
||||
sendToForm: function(name, data) {
|
||||
if (!this.formMM) {
|
||||
dump("Keyboard.jsm: Attempt to send message " + name +
|
||||
" to form but no message manager exists.\n");
|
||||
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.formMM.sendAsyncMessage(name, data);
|
||||
} catch(e) { }
|
||||
@ -91,7 +99,7 @@ this.Keyboard = {
|
||||
ppmm.addMessageListener('Keyboard:' + name, this);
|
||||
}
|
||||
|
||||
for (let name of this._systemMessageName) {
|
||||
for (let name of this._systemMessageNames) {
|
||||
ppmm.addMessageListener('System:' + name, this);
|
||||
}
|
||||
|
||||
@ -110,7 +118,7 @@ this.Keyboard = {
|
||||
}
|
||||
|
||||
if (topic == 'oop-frameloader-crashed' ||
|
||||
topic == 'message-manager-close') {
|
||||
topic == 'message-manager-close') {
|
||||
if (this.formMM == mm) {
|
||||
// The application has been closed unexpectingly. Let's tell the
|
||||
// keyboard app that the focus has been lost.
|
||||
@ -152,28 +160,26 @@ this.Keyboard = {
|
||||
// If we get a 'Keyboard:XXX'/'System:XXX' message, check that the sender
|
||||
// has the required permission.
|
||||
let mm;
|
||||
let isKeyboardRegistration = msg.name == "Keyboard:Register" ||
|
||||
msg.name == "Keyboard:Unregister";
|
||||
if (msg.name.indexOf("Keyboard:") === 0 ||
|
||||
msg.name.indexOf("System:") === 0) {
|
||||
if (!this.formMM && !isKeyboardRegistration) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Assert the permission based on the prefix of the message.
|
||||
let permName;
|
||||
if (msg.name.startsWith("Keyboard:")) {
|
||||
permName = "input";
|
||||
} else if (msg.name.startsWith("System:")) {
|
||||
permName = "input-manage";
|
||||
}
|
||||
|
||||
// There is no permission to check (nor we need to get the mm)
|
||||
// for Form: messages.
|
||||
if (permName) {
|
||||
mm = Utils.getMMFromMessage(msg);
|
||||
|
||||
// That should never happen.
|
||||
if (!mm) {
|
||||
dump("!! No message manager found for " + msg.name);
|
||||
dump("Keyboard.jsm: Message " + msg.name + " has no message manager.");
|
||||
return;
|
||||
}
|
||||
|
||||
let perm = (msg.name.indexOf("Keyboard:") === 0) ? "input"
|
||||
: "input-manage";
|
||||
|
||||
if (!isKeyboardRegistration && !Utils.checkPermissionForMM(mm, perm)) {
|
||||
dump("Keyboard message " + msg.name +
|
||||
" from a content process with no '" + perm + "' privileges.");
|
||||
if (!Utils.checkPermissionForMM(mm, permName)) {
|
||||
dump("Keyboard.jsm: Message " + msg.name +
|
||||
" from a content process with no '" + permName + "' privileges.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -229,6 +235,9 @@ this.Keyboard = {
|
||||
case 'System:SetSelectedOptions':
|
||||
this.setSelectedOption(msg);
|
||||
break;
|
||||
case 'System:SetSupportsSwitchingTypes':
|
||||
this.setSupportsSwitchingTypes(msg);
|
||||
break;
|
||||
case 'Keyboard:SetSelectionRange':
|
||||
this.setSelectionRange(msg);
|
||||
break;
|
||||
@ -341,6 +350,10 @@ this.Keyboard = {
|
||||
},
|
||||
|
||||
removeFocus: function keyboardRemoveFocus() {
|
||||
if (!this.formMM) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.sendToForm('Forms:Select:Blur', {});
|
||||
},
|
||||
|
||||
@ -369,10 +382,14 @@ this.Keyboard = {
|
||||
},
|
||||
|
||||
getContext: function keyboardGetContext(msg) {
|
||||
if (this._layouts) {
|
||||
this.sendToKeyboard('Keyboard:LayoutsChange', this._layouts);
|
||||
if (!this.formMM) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.sendToKeyboard('Keyboard:SupportsSwitchingTypesChange', {
|
||||
types: this._supportsSwitchingTypes
|
||||
});
|
||||
|
||||
this.sendToForm('Forms:GetContext', msg.data);
|
||||
},
|
||||
|
||||
@ -384,17 +401,28 @@ this.Keyboard = {
|
||||
this.sendToForm('Forms:EndComposition', msg.data);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the number of keyboard layouts active from keyboard_manager
|
||||
*/
|
||||
_layouts: null,
|
||||
setLayouts: function keyboardSetLayoutCount(layouts) {
|
||||
setSupportsSwitchingTypes: function setSupportsSwitchingTypes(msg) {
|
||||
this._supportsSwitchingTypes = msg.data.types;
|
||||
this.sendToKeyboard('Keyboard:SupportsSwitchingTypesChange', msg.data);
|
||||
},
|
||||
// XXX: To be removed with mozContentEvent support from shell.js
|
||||
setLayouts: function keyboardSetLayouts(layouts) {
|
||||
// The input method plugins may not have loaded yet,
|
||||
// cache the layouts so on init we can respond immediately instead
|
||||
// of going back and forth between keyboard_manager
|
||||
this._layouts = layouts;
|
||||
var types = [];
|
||||
|
||||
this.sendToKeyboard('Keyboard:LayoutsChange', layouts);
|
||||
Object.keys(layouts).forEach((type) => {
|
||||
if (layouts[type] > 1) {
|
||||
types.push(type);
|
||||
}
|
||||
});
|
||||
|
||||
this._supportsSwitchingTypes = types;
|
||||
|
||||
this.sendToKeyboard('Keyboard:SupportsSwitchingTypesChange', {
|
||||
types: types
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -136,7 +136,7 @@ function MozInputMethodManager(win) {
|
||||
}
|
||||
|
||||
MozInputMethodManager.prototype = {
|
||||
_supportsSwitching: false,
|
||||
supportsSwitchingForCurrentInputContext: false,
|
||||
_window: null,
|
||||
|
||||
classID: Components.ID("{7e9d7280-ef86-11e2-b778-0800200c9a66}"),
|
||||
@ -161,7 +161,7 @@ MozInputMethodManager.prototype = {
|
||||
if (!WindowMap.isActive(this._window)) {
|
||||
return false;
|
||||
}
|
||||
return this._supportsSwitching;
|
||||
return this.supportsSwitchingForCurrentInputContext;
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
@ -169,6 +169,12 @@ MozInputMethodManager.prototype = {
|
||||
return;
|
||||
}
|
||||
cpmmSendAsyncMessageWithKbID(this, 'Keyboard:RemoveFocus', {});
|
||||
},
|
||||
|
||||
setSupportsSwitchingTypes: function(types) {
|
||||
cpmm.sendAsyncMessage('System:SetSupportsSwitchingTypes', {
|
||||
types: types
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -184,7 +190,7 @@ MozInputMethod.prototype = {
|
||||
|
||||
_inputcontext: null,
|
||||
_wrappedInputContext: null,
|
||||
_layouts: {},
|
||||
_supportsSwitchingTypes: [],
|
||||
_window: null,
|
||||
|
||||
classID: Components.ID("{4607330d-e7d2-40a4-9eb8-43967eae0142}"),
|
||||
@ -208,7 +214,7 @@ MozInputMethod.prototype = {
|
||||
cpmm.addWeakMessageListener('Keyboard:Blur', this);
|
||||
cpmm.addWeakMessageListener('Keyboard:SelectionChange', this);
|
||||
cpmm.addWeakMessageListener('Keyboard:GetContext:Result:OK', this);
|
||||
cpmm.addWeakMessageListener('Keyboard:LayoutsChange', this);
|
||||
cpmm.addWeakMessageListener('Keyboard:SupportsSwitchingTypesChange', this);
|
||||
cpmm.addWeakMessageListener('InputRegistry:Result:OK', this);
|
||||
cpmm.addWeakMessageListener('InputRegistry:Result:Error', this);
|
||||
},
|
||||
@ -221,7 +227,7 @@ MozInputMethod.prototype = {
|
||||
cpmm.removeWeakMessageListener('Keyboard:Blur', this);
|
||||
cpmm.removeWeakMessageListener('Keyboard:SelectionChange', this);
|
||||
cpmm.removeWeakMessageListener('Keyboard:GetContext:Result:OK', this);
|
||||
cpmm.removeWeakMessageListener('Keyboard:LayoutsChange', this);
|
||||
cpmm.removeWeakMessageListener('Keyboard:SupportsSwitchingTypesChange', this);
|
||||
cpmm.removeWeakMessageListener('InputRegistry:Result:OK', this);
|
||||
cpmm.removeWeakMessageListener('InputRegistry:Result:Error', this);
|
||||
this.setActive(false);
|
||||
@ -253,8 +259,8 @@ MozInputMethod.prototype = {
|
||||
case 'Keyboard:GetContext:Result:OK':
|
||||
this.setInputContext(data);
|
||||
break;
|
||||
case 'Keyboard:LayoutsChange':
|
||||
this._layouts = data;
|
||||
case 'Keyboard:SupportsSwitchingTypesChange':
|
||||
this._supportsSwitchingTypes = data.types;
|
||||
break;
|
||||
|
||||
case 'InputRegistry:Result:OK':
|
||||
@ -299,13 +305,12 @@ MozInputMethod.prototype = {
|
||||
this._inputcontext.destroy();
|
||||
this._inputcontext = null;
|
||||
this._wrappedInputContext = null;
|
||||
this._mgmt._supportsSwitching = false;
|
||||
this._mgmt.supportsSwitchingForCurrentInputContext = false;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
this._mgmt._supportsSwitching = this._layouts[data.inputType] ?
|
||||
this._layouts[data.inputType] > 1 :
|
||||
false;
|
||||
this._mgmt.supportsSwitchingForCurrentInputContext =
|
||||
(this._supportsSwitchingTypes.indexOf(data.inputType) !== -1);
|
||||
|
||||
this._inputcontext = new MozInputContext(data);
|
||||
this._inputcontext.init(this._window);
|
||||
|
@ -21,9 +21,10 @@ support-files =
|
||||
[test_bug1059163.html]
|
||||
[test_bug1066515.html]
|
||||
[test_bug1175399.html]
|
||||
[test_bug1137557.html]
|
||||
[test_sendkey_cancel.html]
|
||||
[test_setSupportsSwitching.html]
|
||||
[test_sync_edit.html]
|
||||
[test_two_inputs.html]
|
||||
[test_two_selects.html]
|
||||
[test_unload.html]
|
||||
[test_bug1137557.html]
|
||||
|
134
dom/inputmethod/mochitest/test_setSupportsSwitching.html
Normal file
134
dom/inputmethod/mochitest/test_setSupportsSwitching.html
Normal file
@ -0,0 +1,134 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1197682
|
||||
-->
|
||||
<head>
|
||||
<title>Test inputcontext#inputType and MozInputMethodManager#supportsSwitching()</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=1197682">Mozilla Bug 1197682</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 input = content.document.body.firstElementChild;
|
||||
|
||||
let i = 1;
|
||||
|
||||
input.focus();
|
||||
|
||||
addMessageListener('test:next', function() {
|
||||
i++;
|
||||
switch (i) {
|
||||
case 2:
|
||||
content.document.body.children[1].focus();
|
||||
i++; // keep the same count with the parent frame.
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
content.document.body.lastElementChild.focus();
|
||||
i++; // keep the same count with the parent frame.
|
||||
|
||||
break;
|
||||
|
||||
case 6:
|
||||
content.document.body.lastElementChild.blur();
|
||||
|
||||
break;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function runTest() {
|
||||
let im = navigator.mozInputMethod;
|
||||
|
||||
let i = 0;
|
||||
im.oninputcontextchange = function(evt) {
|
||||
var inputcontext = navigator.mozInputMethod.inputcontext;
|
||||
|
||||
i++;
|
||||
switch (i) {
|
||||
case 1:
|
||||
ok(!!inputcontext, '1) Receving the input context');
|
||||
is(inputcontext.inputType, 'text', '1) input type');
|
||||
is(im.mgmt.supportsSwitching(), true, '1) supports switching');
|
||||
|
||||
mm.sendAsyncMessage('test:next');
|
||||
break;
|
||||
|
||||
case 2:
|
||||
is(inputcontext, null, '2) Receving null inputcontext');
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ok(!!inputcontext, '3) Receving the input context');
|
||||
is(inputcontext.inputType, 'number', '3) input type');
|
||||
is(im.mgmt.supportsSwitching(), false, '3) supports switching');
|
||||
|
||||
mm.sendAsyncMessage('test:next');
|
||||
break;
|
||||
|
||||
case 4:
|
||||
is(inputcontext, null, '4) Receving null inputcontext');
|
||||
|
||||
break;
|
||||
|
||||
case 5:
|
||||
ok(!!inputcontext, '5) Receving the input context');
|
||||
is(inputcontext.inputType, 'password', '5) input type');
|
||||
is(im.mgmt.supportsSwitching(), true, '5) supports switching');
|
||||
|
||||
mm.sendAsyncMessage('test:next');
|
||||
break;
|
||||
|
||||
case 6:
|
||||
is(inputcontext, null, '6) Receving null inputcontext');
|
||||
is(im.mgmt.supportsSwitching(), false, '6) supports switching');
|
||||
|
||||
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);
|
||||
// Set text and password inputs as supports switching (and not supported for number type)
|
||||
im.mgmt.setSupportsSwitchingTypes(['text', 'password']);
|
||||
|
||||
let iframe = document.createElement('iframe');
|
||||
iframe.src = 'data:text/html,<html><body>' +
|
||||
'<input type="text">' +
|
||||
'<input type="number">' +
|
||||
'<input type="password">' +
|
||||
'</body></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>
|
@ -119,13 +119,14 @@ interface MozInputMethod : EventTarget {
|
||||
*/
|
||||
[JSImplementation="@mozilla.org/b2g-imm;1",
|
||||
Pref="dom.mozInputMethod.enabled",
|
||||
CheckAnyPermissions="input"]
|
||||
CheckAnyPermissions="input input-manage"]
|
||||
interface MozInputMethodManager {
|
||||
/**
|
||||
* Ask the OS to show a list of available inputs for users to switch from.
|
||||
* OS should sliently ignore this request if the app is currently not the
|
||||
* active one.
|
||||
*/
|
||||
[CheckAllPermissions="input"]
|
||||
void showAll();
|
||||
|
||||
/**
|
||||
@ -133,16 +134,18 @@ interface MozInputMethodManager {
|
||||
* OS should sliently ignore this request if the app is currently not the
|
||||
* active one.
|
||||
*/
|
||||
[CheckAllPermissions="input"]
|
||||
void next();
|
||||
|
||||
/**
|
||||
* If this method returns true, it is recommented that the input app provides
|
||||
* If this method returns true, it is recommended that the input app provides
|
||||
* a shortcut that would invoke the next() method above, for easy switching
|
||||
* between inputs -- i.e. show a "global" button on screen if the input app
|
||||
* implements an on-screen virtual keyboard.
|
||||
*
|
||||
* The returning value is depend on the inputType of the current input context.
|
||||
*/
|
||||
[CheckAllPermissions="input"]
|
||||
boolean supportsSwitching();
|
||||
|
||||
/**
|
||||
@ -150,7 +153,18 @@ interface MozInputMethodManager {
|
||||
* OS should sliently ignore this request if the app is currently not the
|
||||
* active one.
|
||||
*/
|
||||
[CheckAllPermissions="input"]
|
||||
void hide();
|
||||
|
||||
/**
|
||||
* Update Gecko with information on the input types which supportsSwitching()
|
||||
* should return ture.
|
||||
*
|
||||
* @param types Array of input types in which supportsSwitching() should
|
||||
* return true.
|
||||
*/
|
||||
[CheckAllPermissions="input-manage"]
|
||||
void setSupportsSwitchingTypes(sequence<MozInputMethodInputContextInputTypes> types);
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user