Confirmed users
478
edits
(Remove the IDL draft) |
|||
(47 intermediate revisions by 8 users not shown) | |||
Line 1: | Line 1: | ||
__TOC__ | __TOC__ | ||
Line 18: | Line 17: | ||
# [https://groups.google.com/forum/?fromgroups#!topic/mozilla.dev.webapi/Vs3-HGv9NNw WebAPI mailing list post] | # [https://groups.google.com/forum/?fromgroups#!topic/mozilla.dev.webapi/Vs3-HGv9NNw WebAPI mailing list post] | ||
# [https://groups.google.com/forum/?fromgroups=#!topic/mozilla.dev.webapi/A7dIBaR3lpU Extended API mailing list post] | # [https://groups.google.com/forum/?fromgroups=#!topic/mozilla.dev.webapi/A7dIBaR3lpU Extended API mailing list post] | ||
# [https://groups.google.com/forum/#!msg/mozilla.dev.webapi/nZLOEvEL3Tk/M-nSnP6HZgoJ Polished Keyboard API] | |||
Implementation: | Implementation: | ||
#{{bug|737110}} - Bug 737110 - Virtual Keyboard API | #{{bug|737110}} - Bug 737110 - Virtual Keyboard API | ||
== Features == | == Features == | ||
Line 33: | Line 26: | ||
The Virtual Keyboard/IME API supports the following features: | The Virtual Keyboard/IME API supports the following features: | ||
* Notifies the VKB app when the focus text field was changing in other | * Notifies the VKB app when the focus text field was changing in other apps | ||
apps | |||
* Allow user to manual hide the keyboard. Check {{bug|737110}}. | * Allow user to manual hide the keyboard. Check {{bug|737110}}. | ||
* The VKB app should be responsive to properties and the state of the input field (more than HTML5 input type, including current content, cursor position, x-inputmode {{bug|796544}}). | * The VKB app should be responsive to properties and the state of the input field (more than HTML5 input type, including current content, cursor position, x-inputmode {{bug|796544}}). | ||
Line 45: | Line 37: | ||
* The return key label of the VKB can be customized. | * The return key label of the VKB can be customized. | ||
== Proposed | == Proposed Manifest of a 3rd-Party IME == | ||
Just like any other apps, keyboard apps register themselves in the same apps registry. We extend the manifest syntax here to describe layout(s) available in a given keyboard app. Gaia will be paring the manifest. There are 3 special fields to distinguish and describe a 3rd-party IME: | |||
* [Line 4] a "role" field with value "keyboard" declares it's an IME app. Homescreen app will ignore some role types when displaying app icons, and "keyboard" is one of them. (see {{bug|892397}}) | |||
* [Line 6-8] a "permissions" field that requests "keyboard" permission. All IME apps need this permission for sending input keys and updating the value of a input field. | |||
* [Line 9-30] a "inputs" field specifies supported layouts. Each layout is described in a key-value pair, where the key represents the layout name (will be shown up on Settings app with the app name), and the value describes the detailed information of the layout, including launch path of the layout and supported input types. (See [[#Layout Matching Algorithm]]) | |||
** The allowed value in "types" field is a subset of [http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#attr-input-type type attribute of input element]: text, search, tel, number, url, email. Other types will be ignored by FxOS Gaia in the initial version because at this point UI for <select> and <input type=date> (called "value selectors") are not open for 3rd-party implementation. | |||
{ | |||
"name": "3rd-party Keyboard", | |||
"description": "3rd-party Keyboard", | |||
"type": "privilege", | |||
"role": "input", | |||
"launch_path": "/settings.html", | |||
"developer": { | |||
"name": "developer's name", | |||
"url": "https://keyboard.example.com" | |||
}, | |||
"permissions": { | |||
"input": {} | |||
}, | |||
"inputs": { | |||
"en": { | |||
"launch_path": "/index.html#en", | |||
"name": "English", | |||
"description": "English layout", | |||
"types": ["url", "text"], | |||
"locales": { | |||
"en-US": { | |||
"name": "English", | |||
"description": "English layout" | |||
}, | |||
"zh-TW": { | |||
"name": "英文", | |||
"description": "英文鍵盤" | |||
} | |||
} | |||
}, | |||
"en-Dvorak": { | |||
"launch_path": "/index.html#en-Dvorak", | |||
"name": "English (Dvorak)", | |||
"description": "Dvorak layout", | |||
"types": ["url", "text"] | |||
}, | |||
"es": { | |||
"launch_path": "/index.html#es", | |||
"name": "Spanish", | |||
"description": "Spanish layout", | |||
"types": ["url", "text"] | |||
}, | |||
"pt-BR": { | |||
"launch_path": "/index.html#pt-BR", | |||
"name": "Portuguese Brazilian", | |||
"description": "Portuguese Brazilian layout", | |||
"types": ["url", "text"] | |||
}, | |||
"pl": { | |||
"launch_path": "/index.html#pl", | |||
"name": "Polish", | |||
"description": "Polish layout", | |||
"types": ["url", "text"] | |||
}, | |||
"ca": { | |||
"launch_path": "/index.html#ca", | |||
"name": "Catalan", | |||
"description": "Catalan layout", | |||
"types": ["url", "text"] | |||
}, | |||
"cz": { | |||
"launch_path": "/index.html#cz", | |||
"name": "Czech", | |||
"description": "Czech layout", | |||
"types": ["url", "text"] | |||
}, | |||
"fr": { | |||
"launch_path": "/index.html#fr", | |||
"name": "French", | |||
"description": "French layout", | |||
"types": ["url", "text"] | |||
}, | |||
"de": { | |||
"launch_path": "/index.html#de", | |||
"name": "German", | |||
"description": "German layout", | |||
"types": ["url", "text"] | |||
}, | |||
"nb": { | |||
"launch_path": "/index.html#nb", | |||
"name": "Norwegian Bokmal", | |||
"description": "Norwegian Bokmal layout", | |||
"types": ["url", "text"] | |||
}, | |||
"sk": { | |||
"launch_path": "/index.html#sk", | |||
"name": "Slovak", | |||
"description": "Slovak layout", | |||
"types": ["url", "text"] | |||
}, | |||
"tr-Q": { | |||
"launch_path": "/index.html#tr-Q", | |||
"name": "Turkish Q", | |||
"description": "Turkish Q layout", | |||
"types": ["url", "text"] | |||
}, | |||
"tr-F": { | |||
"launch_path": "/index.html#tr-F", | |||
"name": "Turkish F", | |||
"description": "Turkish F layout", | |||
"types": ["url", "text"] | |||
}, | |||
"ro": { | |||
"launch_path": "/index.html#ro", | |||
"name": "Romanian", | |||
"description": "Romanian layout", | |||
"types": ["url", "text"] | |||
}, | |||
"ru": { | |||
"launch_path": "/index.html#ru", | |||
"name": "Russian", | |||
"description": "Russian layout", | |||
"types": ["url", "text"] | |||
}, | |||
"sr-Cyrl": { | |||
"launch_path": "/index.html#sr-Cyrl", | |||
"name": "Serbian (Cyrillic)", | |||
"description": "Serbian (Cyrillic) layout", | |||
"types": ["url", "text"] | |||
}, | |||
"sr-Latn": { | |||
"launch_path": "/index.html#sr-Latn", | |||
"name": "Serbian (Latin)", | |||
"description": "Serbian (Latin) layout", | |||
"types": ["url", "text"] | |||
}, | |||
"ar": { | |||
"launch_path": "/index.html#ar", | |||
"name": "Arabic", | |||
"description": "Arabic layout", | |||
"types": ["url", "text"] | |||
}, | |||
"he": { | |||
"launch_path": "/index.html#he", | |||
"name": "Hebrew", | |||
"description": "Hebrew layout", | |||
"types": ["url", "text"] | |||
}, | |||
"hu": { | |||
"launch_path": "/index.html#hu", | |||
"name": "Hungarian", | |||
"description": "Hungarian layout", | |||
"types": ["url", "text"] | |||
}, | |||
"el": { | |||
"launch_path": "/index.html#el", | |||
"name": "Greek", | |||
"description": "Greek layout", | |||
"types": ["url", "text"] | |||
}, | |||
"zh-Hans-Pinyin": { | |||
"launch_path": "/index.html#zh-Hans-Pinyin", | |||
"name": "Pinyin", | |||
"description": "Pinyin", | |||
"types": ["url", "text"] | |||
}, | |||
"number": { | |||
"launch_path": "/index.html#numberLayout", | |||
"name": "Number", | |||
"description": "Number layout", | |||
"types": ["number"] | |||
} | |||
}, | |||
"locales": { | |||
"en-US": { | |||
"name": "3rd-party Keyboard", | |||
"description": "3rd-party Keyboard" | |||
}, | |||
"zh-TW": { | |||
"name": "第三方鍵盤", | |||
"description": "第三方鍵盤" | |||
} | |||
}, | |||
"default_locale": "en-US" | |||
} | |||
=== Layout Matching Algorithm === | |||
When an input field is focused, if its <code>type</code> attribute is one of the allowed values stated above, it will be used to filter a set of candidate layouts. A candidate layout means it can handle this input type or is possible to let user input all characters that this input field can accept. | |||
For example, if the type of a input is "url", then a layout with "url" or "text" listed in the <code>types</code> of its manifest will be matched. However, if a input field with type "text", then all layouts that support "text" will be matched, but those layouts that only support "url" will not. This is because we believe layouts that can handle "text" could be a fallback for "url" input type, but not vice versa. We also believe "text" could be a fallback for all allowed types stated above. | |||
The | The matching algorithm of keyboard manager in System app is as follows: | ||
# With the given type, find all layouts claims to support the said type and put it into the list. | |||
# Next, find layouts claims to support "text" and put it into the list. Layouts do not get duplicated listing even if it supports both types. | |||
# Present the user with the choice of the layouts available to handle the input field. The order of presenting list is depend on UX design and/or user preferences in Settings. | |||
== Proposed API == | |||
'''The API has made available to privileged apps. See the [http://dxr.mozilla.org/mozilla-central/source/dom/webidl/InputMethod.webidl WebIDL] for the current interface.''' | |||
[https://wiki.mozilla.org/index.php?title=WebAPI/KeboardIME&oldid=1029753#Proposed_API History of this section] | |||
=== Use cases for each of the methods === | === Use cases for each of the methods === | ||
* For a simple virtual keyboard action (send a character and key events w/ each user action), use <code>sendKey()</code>. TODO: should we allow backspace key to be sent from the method? If not, how do send these non-printable characters and it's effect with key events? | * For a simple virtual keyboard action (send a character and key events w/ each user action), use <code>sendKey()</code>. TODO: should we allow backspace key to be sent from the method? If not, how do send these non-printable characters and it's effect with key events? | ||
**[yxl] I perfer to allowing non-printable character, such as backspace key, to be sent, if there is no security issue. This would give the IME more flexibility. | |||
* For spellcheck, autocomplete etc, use surrounding text methods. | * For spellcheck, autocomplete etc, use surrounding text methods. | ||
* For cursor moment helper features, use <code>setSelectionRange()</code> and related attributes. | * For cursor moment helper features, use <code>setSelectionRange()</code> and related attributes. | ||
Line 243: | Line 262: | ||
* Rather rely on entry points in manifest... | * Rather rely on entry points in manifest... | ||
*/ | */ | ||
if (inputContext.inputmode === 'numeric' || inputContext.type === 'number') { | if (inputContext.inputmode === 'numeric' || inputContext.type === 'number') { | ||
['1', '3', '3', '7'].forEach(function (k) { | ['1', '3', '3', '7'].forEach(function (k) { | ||
Line 260: | Line 279: | ||
}, 1000); | }, 1000); | ||
} | } | ||
function stopTyping() { | function stopTyping() { | ||
clearTimeout(timer); | clearTimeout(timer); | ||
} | } | ||
var im = navigator.inputMethod; | var im = navigator.inputMethod; | ||
im.addEventListener('inputcontextchange', function contextchanged(evt) { | im.addEventListener('inputcontextchange', function contextchanged(evt) { | ||
if (evt.inputcontext) { | if (evt.inputcontext) { | ||
Line 276: | Line 295: | ||
} | } | ||
}); | }); | ||
if (im.inputcontext) { | if (im.inputcontext) { | ||
// The webpage here is loaded *after* the user has place the focus on the text field, | // The webpage here is loaded *after* the user has place the focus on the text field, | ||
Line 296: | Line 315: | ||
http://developer.chrome.com/trunk/extensions/input.ime.html | http://developer.chrome.com/trunk/extensions/input.ime.html | ||
[[Category:Web APIs]] |