diff options
author | bshe@chromium.org <bshe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-20 16:32:33 +0000 |
---|---|---|
committer | bshe@chromium.org <bshe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-20 16:32:33 +0000 |
commit | 575ca202312dd7df1dd08f5df2fc55afd1e2ddb8 (patch) | |
tree | 4dfe4e4818d8d4ea8285f82d4dbb136910ed23e4 /ui/keyboard | |
parent | 59661e5adb337208e2a142ab043f819d419b592e (diff) | |
download | chromium_src-575ca202312dd7df1dd08f5df2fc55afd1e2ddb8.zip chromium_src-575ca202312dd7df1dd08f5df2fc55afd1e2ddb8.tar.gz chromium_src-575ca202312dd7df1dd08f5df2fc55afd1e2ddb8.tar.bz2 |
Web Component Virtual Keyboard
Convert existing keyboard to web component keyboard. Also fix touch down state of keys.
BUG=242539, 240346
R=bryeung@chromium.org, miket@chromium.org, stevet@chromium.org
Review URL: https://codereview.chromium.org/15176004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207448 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/keyboard')
24 files changed, 801 insertions, 1473 deletions
diff --git a/ui/keyboard/keyboard_resources.grd b/ui/keyboard/keyboard_resources.grd index e437051..26bad75 100644 --- a/ui/keyboard/keyboard_resources.grd +++ b/ui/keyboard/keyboard_resources.grd @@ -15,22 +15,25 @@ <release seq="1"> <includes> <include name="IDR_KEYBOARD_API_ADAPTER_JS" file="resources/api_adapter.js" type="BINDATA" /> - <include name="IDR_KEYBOARD_COMMON_JS" file="resources/common.js" type="BINDATA" /> - <include name="IDR_KEYBOARD_IMAGES_CHEVRON" file="resources/images/chevron.svg" type="BINDATA" /> - <include name="IDR_KEYBOARD_IMAGES_DEL" file="resources/images/del.svg" type="BINDATA" /> + <include name="IDR_KEYBOARD_CONSTANTS_JS" file="resources/constants.js" type="BINDATA" /> + <include name="IDR_KEYBOARD_ELEMENTS_KEY" file="resources/elements/kb-key.html" type="BINDATA" /> + <include name="IDR_KEYBOARD_ELEMENTS_KEYBOARD" file="resources/elements/kb-keyboard.html" type="BINDATA" /> + <include name="IDR_KEYBOARD_ELEMENTS_KEYSET" file="resources/elements/kb-keyset.html" type="BINDATA" /> + <include name="IDR_KEYBOARD_ELEMENTS_ROW" file="resources/elements/kb-row.html" type="BINDATA" /> <include name="IDR_KEYBOARD_IMAGES_KEYBOARD" file="resources/images/keyboard.svg" type="BINDATA" /> <include name="IDR_KEYBOARD_IMAGES_MIC" file="resources/images/mic.svg" type="BINDATA" /> - <include name="IDR_KEYBOARD_IMAGES_RET" file="resources/images/ret.svg" type="BINDATA" /> - <include name="IDR_KEYBOARD_IMAGES_SHIFT" file="resources/images/shift.svg" type="BINDATA" /> - <include name="IDR_KEYBOARD_IMAGES_SHIFT_DOWN" file="resources/images/shift-down.svg" type="BINDATA" /> - <include name="IDR_KEYBOARD_IMAGES_TAB" file="resources/images/tab.svg" type="BINDATA" /> - <include name="IDR_KEYBOARD_INDEX" file="resources/index.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> - <include name="IDR_KEYBOARD_LAYOUT_US_JS" file="resources/layout_us.js" type="BINDATA" /> - <include name="IDR_KEYBOARD_MAIN_CSS" file="resources/main.css" type="BINDATA" /> + <include name="IDR_KEYBOARD_IMAGES_MIC_GREEN" file="resources/images/mic-green.svg" type="BINDATA" /> + <!-- Don't flatten html file here. Otherwise, webui keyboard will not load the correct css file. --> + <include name="IDR_KEYBOARD_INDEX" file="resources/index.html" allowexternalscript="true" type="BINDATA" /> + <include name="IDR_KEYBOARD_KEYSETS" file="resources/keysets.html" type="BINDATA" /> <include name="IDR_KEYBOARD_MAIN_JS" file="resources/main.js" type="BINDATA" /> <include name="IDR_KEYBOARD_MANIFEST" file="resources/manifest.json" type="BINDATA" /> + <include name="IDR_KEYBOARD_MAIN_CSS" file="resources/main.css" type="BINDATA" /> + <include name="IDR_KEYBOARD_POLYMER" file="resources/polymer.min.js" flattenhtml="true" type="BINDATA" /> + <include name="IDR_KEYBOARD_VOICE_INPUT_JS" file="resources/voice_input.js" type="BINDATA" /> <include name="IDR_KEYBOARD_WEBUI_API_ADAPTER_JS" file="resources/webui/api_adapter.js" type="BINDATA" /> - <include name="IDR_KEYBOARD_WEBUI_LAYOUT_US_JS" file="resources/webui/layout_us.js" type="BINDATA" /> + <include name="IDR_KEYBOARD_WEBUI_CONSTANTS_JS" file="resources/webui/constants.js" type="BINDATA" /> + <include name="IDR_KEYBOARD_WEBUI_KEYSETS" file="resources/webui/keysets.html" type="BINDATA" /> <include name="IDR_KEYBOARD_WEBUI_MAIN_CSS" file="resources/webui/main.css" type="BINDATA" /> </includes> </release> diff --git a/ui/keyboard/keyboard_ui_controller.cc b/ui/keyboard/keyboard_ui_controller.cc index 7cc76d8..7732681 100644 --- a/ui/keyboard/keyboard_ui_controller.cc +++ b/ui/keyboard/keyboard_ui_controller.cc @@ -20,22 +20,24 @@ content::WebUIDataSource* CreateKeyboardUIDataSource() { source->SetDefaultResource(IDR_KEYBOARD_INDEX); - source->AddResourcePath("common.js", IDR_KEYBOARD_COMMON_JS); - source->AddResourcePath("images/chevron.svg", IDR_KEYBOARD_IMAGES_CHEVRON); - source->AddResourcePath("images/del.svg", IDR_KEYBOARD_IMAGES_DEL); - source->AddResourcePath("images/keyboard.svg", IDR_KEYBOARD_IMAGES_KEYBOARD); + source->AddResourcePath("elements/kb-key.html", IDR_KEYBOARD_ELEMENTS_KEY); + source->AddResourcePath("elements/kb-keyboard.html", + IDR_KEYBOARD_ELEMENTS_KEYBOARD); + source->AddResourcePath("elements/kb-keyset.html", + IDR_KEYBOARD_ELEMENTS_KEYSET); + source->AddResourcePath("elements/kb-row.html", IDR_KEYBOARD_ELEMENTS_ROW); source->AddResourcePath("images/mic.svg", IDR_KEYBOARD_IMAGES_MIC); - source->AddResourcePath("images/ret.svg", IDR_KEYBOARD_IMAGES_RET); - source->AddResourcePath("images/shift.svg", IDR_KEYBOARD_IMAGES_SHIFT); - source->AddResourcePath("images/shift_down.svg", - IDR_KEYBOARD_IMAGES_SHIFT_DOWN); - source->AddResourcePath("images/tab.svg", IDR_KEYBOARD_IMAGES_TAB); + source->AddResourcePath("images/mic-green.svg", + IDR_KEYBOARD_IMAGES_MIC_GREEN); source->AddResourcePath("main.js", IDR_KEYBOARD_MAIN_JS); + source->AddResourcePath("polymer.min.js", IDR_KEYBOARD_POLYMER); + source->AddResourcePath("voice_input.js", IDR_KEYBOARD_VOICE_INPUT_JS); // These files are specific to the WebUI version - source->AddResourcePath("layout_us.js", IDR_KEYBOARD_WEBUI_LAYOUT_US_JS); - source->AddResourcePath("main.css", IDR_KEYBOARD_WEBUI_MAIN_CSS); source->AddResourcePath("api_adapter.js", IDR_KEYBOARD_WEBUI_API_ADAPTER_JS); + source->AddResourcePath("constants.js", IDR_KEYBOARD_WEBUI_CONSTANTS_JS); + source->AddResourcePath("keysets.html", IDR_KEYBOARD_WEBUI_KEYSETS); + source->AddResourcePath("main.css", IDR_KEYBOARD_WEBUI_MAIN_CSS); return source; } diff --git a/ui/keyboard/resources/common.js b/ui/keyboard/resources/common.js deleted file mode 100644 index e0e5aca..0000000 --- a/ui/keyboard/resources/common.js +++ /dev/null @@ -1,811 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview A simple virtual keyboard implementation. - */ - -var KEY_MODE = 'key'; -var SHIFT_MODE = 'shift'; -var NUMBER_MODE = 'number'; -var SYMBOL_MODE = 'symbol'; -// TODO(bryeung): tear out all of this mode switching code -var MODES = [KEY_MODE, SHIFT_MODE, NUMBER_MODE, SYMBOL_MODE]; -var currentMode = KEY_MODE; -var enterShiftModeOnSpace = false; -var MODE_CODES = {}; -var MODE_TRANSITIONS = {}; - -MODE_CODES[KEY_MODE] = 0; -MODE_CODES[SHIFT_MODE] = 1; -MODE_CODES[NUMBER_MODE] = 2; -MODE_CODES[SYMBOL_MODE] = 3; - -MODE_TRANSITIONS[KEY_MODE + SHIFT_MODE] = SHIFT_MODE; -MODE_TRANSITIONS[KEY_MODE + NUMBER_MODE] = NUMBER_MODE; -MODE_TRANSITIONS[SHIFT_MODE + SHIFT_MODE] = KEY_MODE; -MODE_TRANSITIONS[SHIFT_MODE + NUMBER_MODE] = NUMBER_MODE; -MODE_TRANSITIONS[NUMBER_MODE + SHIFT_MODE] = SYMBOL_MODE; -MODE_TRANSITIONS[NUMBER_MODE + NUMBER_MODE] = KEY_MODE; -MODE_TRANSITIONS[SYMBOL_MODE + SHIFT_MODE] = NUMBER_MODE; -MODE_TRANSITIONS[SYMBOL_MODE + NUMBER_MODE] = KEY_MODE; - -var KEYBOARDS = {}; - -/** - * The long-press delay in milliseconds before long-press handler is invoked. - * @type {number} - */ -var LONGPRESS_DELAY_MSEC = 500; - -/** - * The repeat delay in milliseconds before a key starts repeating. Use the same - * rate as Chromebook. (See chrome/browser/chromeos/language_preferences.cc) - * @type {number} - */ -var REPEAT_DELAY_MSEC = 500; - -/** - * The repeat interval or number of milliseconds between subsequent keypresses. - * Use the same rate as Chromebook. - * @type {number} - */ -var REPEAT_INTERVAL_MSEC = 50; - -/** - * The keyboard layout name currently in use. - * @type {string} - */ -var currentKeyboardLayout = 'us'; - -/** - * A structure to track the currently repeating key on the keyboard. - */ -var repeatKey = { - /** - * The timer for the delay before repeating behaviour begins. - * @type {number|undefined} - */ - timer: undefined, - - /** - * The interval timer for issuing keypresses of a repeating key. - * @type {number|undefined} - */ - interval: undefined, - - /** - * The key which is currently repeating. - * @type {BaseKey|undefined} - */ - key: undefined, - - /** - * Cancel the repeat timers of the currently active key. - */ - cancel: function() { - clearTimeout(this.timer); - clearInterval(this.interval); - this.timer = undefined; - this.interval = undefined; - this.key = undefined; - } -}; - -/** - * Set the keyboard mode. - * @param {string} mode The new mode. - */ -function setMode(mode) { - currentMode = mode; - - var rows = KEYBOARDS[currentKeyboardLayout]['rows']; - for (var i = 0; i < rows.length; ++i) { - rows[i].showMode(currentMode); - } -} - -/** - * Transition the mode according to the given transition. - * @param {string} transition The transition to take. - */ -function transitionMode(transition) { - setMode(MODE_TRANSITIONS[currentMode + transition]); -} - -/** - * Send the given key to chrome but don't update the keyboard state. - */ -function sendKeyRaw(key) { - var keyIdentifier = key; - - // Fix up some keys to their respective identifiers for convenience. - if (keyIdentifier == ' ') { - keyIdentifier = 'Spacebar'; - } - - var keyEvent = { - keyIdentifier: keyIdentifier - }; - sendKeyEvent(keyEvent); -} - -/** - * Send the given key to chrome, via the experimental extension API. - * Also updates the current keyboard state based on the current state and which - * character was sent. - * @param {string} keyIdentifier The key to send. - */ -function sendKey(keyIdentifier) { - sendKeyRaw(keyIdentifier); - - // Exit shift mode after pressing any key but space. - if (currentMode == SHIFT_MODE && keyIdentifier != 'Spacebar') { - transitionMode(SHIFT_MODE); - } - // Enter shift mode after typing a closing punctuation and then a space for a - // new sentence. - if (enterShiftModeOnSpace) { - enterShiftModeOnSpace = false; - if (currentMode != SHIFT_MODE && keyIdentifier == 'Spacebar') { - setMode(SHIFT_MODE); - } - } - if (currentMode != SHIFT_MODE && - (keyIdentifier == '.' || keyIdentifier == '?' || keyIdentifier == '!')) { - enterShiftModeOnSpace = true; - } -} - -/** - * Add a child div element that represents the content of the given element. - * A child div element that represents a text content is added if - * opt_textContent is given. Otherwise a child element that represents an image - * content is added. If the given element already has a child, the child element - * is modified. - * @param {Element} element The DOM Element to which the content is added. - * @param {string} opt_textContent The text to be inserted. - */ -function addContent(element, opt_textContent) { - if (element.childNodes.length > 0) { - var content = element.childNodes[0]; - if (opt_textContent) { - content.textContent = opt_textContent; - } - return; - } - - var content = document.createElement('div'); - if (opt_textContent) { - content.textContent = opt_textContent; - content.className = 'text-key'; - } else { - content.className = 'image-key'; - } - element.appendChild(content); -} - -/** - * Set up the event handlers necessary to respond to mouse and touch events on - * the virtual keyboard. - * @param {BaseKey} key The BaseKey object corresponding to this key. - * @param {Element} element The top-level DOM Element to set event handlers on. - * @param {Object.<string, function()>} handlers The object that contains key - * event handlers in the following form. - * - * { 'up': keyUpHandler, - * 'down': keyDownHandler, - * 'long': keyLongHandler } - * - * keyDownHandler: Called when the key is pressed. This will be called - * repeatedly when holding a repeating key. - * keyUpHandler: Called when the key is released. This is only called - * once per actual key press. - * keyLongHandler: Called when the key is long-pressed for - * |LONGPRESS_DELAY_MSEC| milliseconds. - * - * The object does not necessarily contain all the handlers above, but - * needs to contain at least one of them. - */ -function setupKeyEventHandlers(key, element, handlers) { - var keyDownHandler = handlers['down']; - var keyUpHandler = handlers['up']; - var keyLongHandler = handlers['long']; - if (!(keyDownHandler || keyUpHandler || keyLongPressHandler)) { - throw new Error('Invalid handlers passed to setupKeyEventHandlers'); - } - - /** - * Handle a key down event on the virtual key. - * @param {UIEvent} evt The UI event which triggered the key down. - */ - var downHandler = function(evt) { - // Prevent any of the system gestures from happening. - evt.preventDefault(); - - // Don't process a key down if the key is already down. - if (key.pressed) { - return; - } - key.pressed = true; - if (keyDownHandler) { - keyDownHandler(); - } - repeatKey.cancel(); - - // Start a repeating timer if there is a repeat interval and a function to - // process key down events. - if (key.repeat && keyDownHandler) { - repeatKey.key = key; - // The timeout for the repeating timer occurs at - // REPEAT_DELAY_MSEC - REPEAT_INTERVAL_MSEC so that the interval - // function can handle all repeat keypresses and will get the first one - // at the correct time. - repeatKey.timer = setTimeout(function() { - repeatKey.timer = undefined; - repeatKey.interval = setInterval(function() { - keyDownHandler(); - }, REPEAT_INTERVAL_MSEC); - }, Math.max(0, REPEAT_DELAY_MSEC - REPEAT_INTERVAL_MSEC)); - } - - if (keyLongHandler) { - // Copy the currentTarget of event, which is neccessary because |evt| can - // be modified before |keyLongHandler| is called. - var evtCopy = {}; - evtCopy.currentTarget = evt.currentTarget; - key.longPressTimer = setTimeout(function() { - keyLongHandler(evtCopy), - clearTimeout(key.longPressTimer); - delete key.longPressTimer; - key.pressed = false; - }, LONGPRESS_DELAY_MSEC); - } - }; - - /** - * Handle a key up event on the virtual key. - * @param {UIEvent} evt The UI event which triggered the key up. - */ - var upHandler = function(evt) { - // Prevent any of the system gestures from happening. - evt.preventDefault(); - - // Reset long-press timer. - if (key.longPressTimer) { - clearTimeout(key.longPressTimer); - delete key.longPressTimer; - } - - // If they key was not actually pressed do not send a key up event. - if (!key.pressed) { - return; - } - key.pressed = false; - - // Cancel running repeat timer for the released key only. - if (repeatKey.key == key) { - repeatKey.cancel(); - } - - if (keyUpHandler) { - keyUpHandler(); - } - }; - - // Setup mouse event handlers. - element.addEventListener('mousedown', downHandler); - element.addEventListener('mouseup', upHandler); - - // Setup touch handlers. - element.addEventListener('touchstart', downHandler); - element.addEventListener('touchend', upHandler); -} - -/** - * Create closure for the sendKey function. - * @param {string} key The key paramater to sendKey. - * @return {function()} A function which calls sendKey(key). - */ -function sendKeyFunction(key) { - return function() { - sendKey(key); - }; -} - -/** - * Plain-old-data class to represent a character. - * @param {string} display The HTML to be displayed. - * @param {string} id The key identifier for this Character. - * @constructor - */ -function Character(display, id) { - this.display = display; - this.keyIdentifier = id; -} - -/** - * Convenience function to make the keyboard data more readable. - * @param {string} display The display for the created Character. - * @param {string} opt_id The id for the created Character. - * @return {Character} A character that contains display and opt_id. If - * opt_id is omitted, display is used as the id. - */ -function C(display, opt_id) { - var id = opt_id || display; - return new Character(display, id); -} - -/** - * An abstract base-class for all keys on the keyboard. - * @constructor - */ -function BaseKey() {} - -BaseKey.prototype = { - /** - * The cell type of this key. Determines the background colour. - * @type {string} - */ - cellType_: '', - - /** - * If true, holding this key will issue repeat keypresses. - * @type {boolean} - */ - repeat_: false, - - /** - * Track the pressed state of the key. This is true if currently pressed. - * @type {boolean} - */ - pressed_: false, - - /** - * Get the repeat behaviour of the key. - * @return {boolean} True if the key will repeat. - */ - get repeat() { - return this.repeat_; - }, - - /** - * Set the repeat behaviour of the key - * @param {boolean} repeat True if the key should repeat. - */ - set repeat(repeat) { - this.repeat_ = repeat; - }, - - /** - * Get the pressed state of the key. - * @return {boolean} True if the key is currently pressed. - */ - get pressed() { - return this.pressed_; - }, - - /** - * Set the pressed state of the key. - * @param {boolean} pressed True if the key is currently pressed. - */ - set pressed(pressed) { - this.pressed_ = pressed; - }, - - /** - * Create the DOM elements for the given keyboard mode. Must be overridden. - * @param {string} mode The keyboard mode to create elements for. - * @return {Element} The top-level DOM Element for the key. - */ - makeDOM: function(mode) { - throw new Error('makeDOM not implemented in BaseKey'); - }, -}; - -/** - * A simple key which displays Characters. - * @param {Object} key The Character for KEY_MODE. - * @param {Object} shift The Character for SHIFT_MODE. - * @param {Object} num The Character for NUMBER_MODE. - * @param {Object} symbol The Character for SYMBOL_MODE. - * @param {string} className An optional class name for the key. - * @constructor - * @extends {BaseKey} - */ -function Key(key, shift, num, symbol, className) { - this.modeElements_ = {}; - this.cellType_ = ''; - this.className_ = (className) ? 'key ' + className : 'key'; - - this.modes_ = {}; - this.modes_[KEY_MODE] = key; - this.modes_[SHIFT_MODE] = shift; - this.modes_[NUMBER_MODE] = num; - this.modes_[SYMBOL_MODE] = symbol; -} - -Key.prototype = { - __proto__: BaseKey.prototype, - - /** @override */ - makeDOM: function(mode) { - if (!this.modes_[mode]) { - return null; - } - - this.modeElements_[mode] = document.createElement('div'); - var element = this.modeElements_[mode]; - element.className = this.className_; - - addContent(element, this.modes_[mode].display); - - setupKeyEventHandlers(this, element, - { 'up': sendKeyFunction(this.modes_[mode].keyIdentifier) }); - return element; - } -}; - -/** - * A key which displays an SVG image. - * @param {string} className The class that provides the image. - * @param {string} keyId The key identifier for the key. - * @param {boolean} opt_repeat True if the key should repeat. - * @constructor - * @extends {BaseKey} - */ -function SvgKey(className, keyId, opt_repeat) { - this.modeElements_ = {}; - this.cellType_ = 'nc'; - this.className_ = className; - this.keyId_ = keyId; - this.repeat_ = opt_repeat || false; -} - -SvgKey.prototype = { - __proto__: BaseKey.prototype, - - /** @override */ - makeDOM: function(mode) { - this.modeElements_[mode] = document.createElement('div'); - this.modeElements_[mode].className = 'key dark'; - this.modeElements_[mode].classList.add(this.className_); - addContent(this.modeElements_[mode]); - - // send the key event on key down if key repeat is enabled - var handler = this.repeat_ ? { 'down' : sendKeyFunction(this.keyId_) } : - { 'up' : sendKeyFunction(this.keyId_) }; - setupKeyEventHandlers(this, this.modeElements_[mode], handler); - - return this.modeElements_[mode]; - } -}; - -/** - * A Key that remains the same through all modes. - * @param {string} className The class name for the key. - * @param {string} content The display text for the key. - * @param {string} keyId The key identifier for the key. - * @constructor - * @extends {BaseKey} - */ -function SpecialKey(className, content, keyId) { - this.modeElements_ = {}; - this.cellType_ = 'nc'; - this.content_ = content; - this.keyId_ = keyId; - this.className_ = className; -} - -SpecialKey.prototype = { - __proto__: BaseKey.prototype, - - /** @override */ - makeDOM: function(mode) { - this.modeElements_[mode] = document.createElement('div'); - this.modeElements_[mode].className = 'key dark'; - this.modeElements_[mode].classList.add(this.className_); - addContent(this.modeElements_[mode], this.content_); - - setupKeyEventHandlers(this, this.modeElements_[mode], - { 'up': sendKeyFunction(this.keyId_) }); - - return this.modeElements_[mode]; - } -}; - -/** - * A shift key. - * @constructor - * @param {string} className The class name for the key. - * @extends {BaseKey} - */ -function ShiftKey(className) { - this.modeElements_ = {}; - this.cellType_ = 'nc'; - this.className_ = className; -} - -ShiftKey.prototype = { - __proto__: BaseKey.prototype, - - /** @override */ - makeDOM: function(mode) { - this.modeElements_[mode] = document.createElement('div'); - this.modeElements_[mode].className = 'key shift dark'; - this.modeElements_[mode].classList.add(this.className_); - - if (mode == KEY_MODE || mode == SHIFT_MODE) { - addContent(this.modeElements_[mode]); - } else if (mode == NUMBER_MODE) { - addContent(this.modeElements_[mode], 'more'); - } else if (mode == SYMBOL_MODE) { - addContent(this.modeElements_[mode], '#123'); - } - - if (mode == SHIFT_MODE || mode == SYMBOL_MODE) { - this.modeElements_[mode].classList.add('moddown'); - } else { - this.modeElements_[mode].classList.remove('moddown'); - } - - setupKeyEventHandlers(this, this.modeElements_[mode], - { 'down': function() { - transitionMode(SHIFT_MODE); - }}); - - return this.modeElements_[mode]; - }, -}; - -/** - * The symbol key: switches the keyboard into symbol mode. - * @constructor - * @extends {BaseKey} - */ -function SymbolKey() { - this.modeElements_ = {}; - this.cellType_ = 'nc'; -} - -SymbolKey.prototype = { - __proto__: BaseKey.prototype, - - /** @override */ - makeDOM: function(mode, height) { - this.modeElements_[mode] = document.createElement('div'); - this.modeElements_[mode].className = 'key symbol dark'; - - if (mode == KEY_MODE || mode == SHIFT_MODE) { - addContent(this.modeElements_[mode], '#123'); - } else if (mode == NUMBER_MODE || mode == SYMBOL_MODE) { - addContent(this.modeElements_[mode], 'abc'); - } - - if (mode == NUMBER_MODE || mode == SYMBOL_MODE) { - this.modeElements_[mode].classList.add('moddown'); - } else { - this.modeElements_[mode].classList.remove('moddown'); - } - - setupKeyEventHandlers(this, this.modeElements_[mode], - { 'down': function() { - transitionMode(NUMBER_MODE); - }}); - - return this.modeElements_[mode]; - } -}; - -/** - * The ".com" key. - * @constructor - * @extends {BaseKey} - */ -function DotComKey() { - this.modeElements_ = {}; - this.cellType_ = 'nc'; -} - -DotComKey.prototype = { - __proto__: BaseKey.prototype, - - /** @override */ - makeDOM: function(mode) { - this.modeElements_[mode] = document.createElement('div'); - this.modeElements_[mode].className = 'key com dark'; - addContent(this.modeElements_[mode], '.com'); - - setupKeyEventHandlers(this, this.modeElements_[mode], - { 'up': function() { - sendKeyRaw('.'); - sendKeyRaw('c'); - sendKeyRaw('o'); - sendKeyRaw('m'); - }}); - - return this.modeElements_[mode]; - } -}; - -/** - * The key that hides the keyboard. - * @constructor - * @extends {BaseKey} - */ -function HideKeyboardKey() { - this.modeElements_ = {}; - this.cellType_ = 'nc'; -} - -HideKeyboardKey.prototype = { - __proto__: BaseKey.prototype, - - /** @override */ - makeDOM: function(mode) { - this.modeElements_[mode] = document.createElement('div'); - this.modeElements_[mode].className = 'key hide dark'; - addContent(this.modeElements_[mode]); - - setupKeyEventHandlers(this, this.modeElements_[mode], - { 'down': function() { console.log('Hide the keyboard!'); } }); - - return this.modeElements_[mode]; - } -}; - -/** - * The mic key: activate speech input. - * @constructor - * @extends {BaseKey} - */ -function MicKey() { - this.modeElements_ = {}; - this.recognition_ = new webkitSpeechRecognition(); - this.recognition_.onstart = this.onStartHandler.bind(this); - this.recognition_.onresult = this.onResultHandler.bind(this); - this.recognition_.onerror = this.onErrorHandler.bind(this); - this.recognition_.onend = this.onEndHandler.bind(this); - this.finalResult_ = ''; - this.recognizing_ = false; - this.cellType_ = 'nc'; -} - -MicKey.prototype = { - __proto__: BaseKey.prototype, - - /** - * Event handler for mouse/touch down events. - */ - onDown: function() { - if (this.recognizing_) { - this.recognition_.stop(); - return; - } - this.recognition_.start(); - }, - - /** - * Speech recognition started. Change mic key's icon. - */ - onStartHandler: function() { - this.recognizing_ = true; - this.finalResult_ = ''; - for (var i = 0; i < MODES.length; ++i) - this.modeElements_[MODES[i]].classList.add('start'); - }, - - /** - * Speech recognizer returns a result. - * @param{Event} e The SpeechRecognition event that is raised each time there - * are any changes to interim or final results. - */ - onResultHandler: function(e) { - for (var i = e.resultIndex; i < e.results.length; i++) { - if (e.results[i].isFinal) - this.finalResult_ = e.results[i][0].transcript; - } - for (var i = 0; i < this.finalResult_.length; i++) { - sendKeyRaw(this.finalResult_.charAt(i)); - } - }, - - /** - * Speech recognizer returns an error. - * @param{Event} e The SpeechRecognitionError event that is raised each time - * there is an error. - */ - onErrorHandler: function(e) { - console.error('error code = ' + e.error); - }, - - /** - * Speech recognition ended. Reset mic key's icon. - */ - onEndHandler: function() { - for (var i = 0; i < MODES.length; ++i) - this.modeElements_[MODES[i]].classList.remove('start'); - - this.recognizing_ = false; - }, - - /** @override */ - makeDOM: function(mode) { - this.modeElements_[mode] = document.createElement('div'); - this.modeElements_[mode].className = 'key mic'; - addContent(this.modeElements_[mode]); - - setupKeyEventHandlers(this, this.modeElements_[mode], - { 'down': this.onDown.bind(this) }); - - return this.modeElements_[mode]; - } -}; - -/** - * A container for keys. - * @param {number} position The position of the row (0-3). - * @param {Array.<BaseKey>} keys The keys in the row. - * @constructor - */ -function Row(position, keys) { - this.position_ = position; - this.keys_ = keys; - this.element_ = null; - this.modeElements_ = {}; -} - -Row.prototype = { - /** - * Create the DOM elements for the row. - * @return {Element} The top-level DOM Element for the row. - */ - makeDOM: function() { - this.element_ = document.createElement('div'); - this.element_.className = 'row'; - for (var i = 0; i < MODES.length; ++i) { - var mode = MODES[i]; - this.modeElements_[mode] = document.createElement('div'); - this.modeElements_[mode].style.display = 'none'; - this.element_.appendChild(this.modeElements_[mode]); - } - - for (var j = 0; j < this.keys_.length; ++j) { - var key = this.keys_[j]; - for (var i = 0; i < MODES.length; ++i) { - var keyDom = key.makeDOM(MODES[i]); - if (keyDom) { - this.modeElements_[MODES[i]].appendChild(keyDom); - } - } - } - - for (var i = 0; i < MODES.length; ++i) { - var clearingDiv = document.createElement('div'); - clearingDiv.style.clear = 'both'; - this.modeElements_[MODES[i]].appendChild(clearingDiv); - } - - return this.element_; - }, - - /** - * Shows the given mode. - * @param {string} mode The mode to show. - */ - showMode: function(mode) { - for (var i = 0; i < MODES.length; ++i) { - this.modeElements_[MODES[i]].style.display = 'none'; - } - this.modeElements_[mode].style.display = '-webkit-box'; - }, - - /** - * Returns the size of keys this row contains. - * @return {number} The size of keys. - */ - get length() { - return this.keys_.length; - } -}; diff --git a/ui/keyboard/resources/constants.js b/ui/keyboard/resources/constants.js new file mode 100644 index 0000000..f5700da --- /dev/null +++ b/ui/keyboard/resources/constants.js @@ -0,0 +1,24 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * Aspect ratio of keyboard. + * @type {number} + */ +var ASPECT_RATIO = 4.5; + +/** + * Ratio of key height and font size. + * @type {number} + */ +var FONT_SIZE_RATIO = 3.5; + +/** + * The number of rows in each keyset. + * @type {number} + */ +// TODO(bshe): The number of rows should equal to the number of kb-row elements +// in kb-keyset. Remove this variable once figure out how to calculate the +// number from keysets. +var ROW_LENGTH = 4; diff --git a/ui/keyboard/resources/elements/kb-key.html b/ui/keyboard/resources/elements/kb-key.html new file mode 100644 index 0000000..c0d2556 --- /dev/null +++ b/ui/keyboard/resources/elements/kb-key.html @@ -0,0 +1,56 @@ +<!-- + -- Copyright (c) 2013 The Chromium Authors. All rights reserved. + -- Use of this source code is governed by a BSD-style license that can be + -- found in the LICENSE file. + --> + +<element name="kb-key" attributes="toKeyset char repeat" on-pointerdown="down" + on-pointerup="up"> + <template> + <style> + @host { + * { + -webkit-box-flex: 1; + display: -webkit-box; + position: relative; + background-position: center center; + background-repeat: no-repeat; + background-size: contain; + } + } + .key { + bottom: 0; + left: 0; + height: 1.2em; + margin: auto; + position: absolute; + right: 0; + top: 0; + text-align: center; + } + </style> + <div id="key" class="key"> + <content></content> + </div> + </template> + <script> + Polymer.register(this, { + repeat: false, + down: function(event) { + var detail = { + char: this.char || this.textContent, + toKeyset: this.toKeyset, + repeat: this.repeat + }; + this.send('key-down', detail); + }, + up: function(event) { + var detail = { + char: this.char || this.textContent, + toKeyset: this.toKeyset + }; + this.send('key-up', detail); + } + }); + </script> +</element> diff --git a/ui/keyboard/resources/elements/kb-keyboard.html b/ui/keyboard/resources/elements/kb-keyboard.html new file mode 100644 index 0000000..0f19ccd --- /dev/null +++ b/ui/keyboard/resources/elements/kb-keyboard.html @@ -0,0 +1,159 @@ +<!-- + -- Copyright (c) 2013 The Chromium Authors. All rights reserved. + -- Use of this source code is governed by a BSD-style license that can be + -- found in the LICENSE file. + --> + +<element name="kb-keyboard" on-key-over="keyOver" on-key-up="keyUp" + on-key-down="keyDown" attributes="keyset rows"> + <template> + <content select="#{{keyset}}"></content> + </template> + <script> + /** + * The long-press delay in milliseconds before long-press handler is + * invoked. + * @type {number} + */ + var LONGPRESS_DELAY_MSEC = 500; + + /** + * The repeat delay in milliseconds before a key starts repeating. Use the + * same rate as Chromebook. + * (See chrome/browser/chromeos/language_preferences.cc) + * @type {number} + */ + var REPEAT_DELAY_MSEC = 500; + + /** + * The repeat interval or number of milliseconds between subsequent + * keypresses. Use the same rate as Chromebook. + * @type {number} + */ + var REPEAT_INTERVAL_MSEC = 50; + + /** + * The boolean to decide if keyboard should transit to upper case keyset + * when spacebar is pressed. If a closing punctuation is followed by a + * spacebar, keyboard should automatically transit to upper case. + * @type {boolean} + */ + var enterUpperOnSpace = false; + + /** + * A structure to track the currently repeating key on the keyboard. + */ + var repeatKey = { + /** + * The timer for the delay before repeating behaviour begins. + * @type {number|undefined} + */ + timer: undefined, + + /** + * The interval timer for issuing keypresses of a repeating key. + * @type {number|undefined} + */ + interval: undefined, + + /** + * The key which is currently repeating. + * @type {BaseKey|undefined} + */ + key: undefined, + + /** + * Cancel the repeat timers of the currently active key. + */ + cancel: function() { + clearTimeout(this.timer); + clearInterval(this.interval); + this.timer = undefined; + this.interval = undefined; + this.key = undefined; + } + }; + + Polymer.register(this, { + lastPressedKey: null, + voiceInput_: null, + + ready: function() { + this.voiceInput_ = new VoiceInput(this); + }, + + /** + * Handles key-down event that is sent by kb-key. + * @param {CustomEvent} event The key-down event dispatched by kb-key. + * @param {Object} detail The detail of pressed kb-key. + */ + keyDown: function(event, detail) { + var toKeyset = detail.toKeyset; + if (this.lastPressedKey) + this.lastPressedKey.classList.remove('active'); + this.lastPressedKey = event.target; + this.lastPressedKey.classList.add('active'); + repeatKey.cancel(); + if (detail.repeat) { + sendKey(detail.char); + repeatKey.key = this.lastPressedKey; + repeatKey.timer = setTimeout(function() { + repeatKey.timer = undefined; + repeatKey.interval = setInterval(function() { + sendKey(detail.char); + }, REPEAT_INTERVAL_MSEC); + }, Math.max(0, REPEAT_DELAY_MSEC - REPEAT_INTERVAL_MSEC)); + } + }, + + /** + * Handles key-up event that is sent by kb-key. + * @param {CustomEvent} event The key-up event dispatched by kb-key. + * @param {Object} detail The detail of pressed kb-key. + */ + keyUp: function(event, detail) { + this.lastPressedKey.classList.remove('active'); + if (this.lastPressedKey != event.target) + return; + if (repeatKey.key == event.target) { + repeatKey.cancel(); + return; + } + var toKeyset = detail.toKeyset; + // Keyset transtion key. + if (toKeyset) { + this.keyset = toKeyset; + } + var char = detail.char; + if (enterUpperOnSpace) { + enterUpperOnSpace = false; + if (char == 'Spacebar') + this.keyset = 'upper'; + } + switch(char) { + case 'Invalid': + return; + case 'Mic': + this.voiceInput_.onDown(); + return; + case '.': + case '?': + case '!': + enterUpperOnSpace = true; + break; + case 'Tab': + case 'Spacebar': + case 'Enter': + sendKey(char); + return; + default: + break; + } + for (var i = 0; i < char.length; i++) { + sendKey(char.charAt(i)); + } + } + }); + </script> +</element> + diff --git a/ui/keyboard/resources/elements/kb-keyset.html b/ui/keyboard/resources/elements/kb-keyset.html new file mode 100644 index 0000000..c953aed --- /dev/null +++ b/ui/keyboard/resources/elements/kb-keyset.html @@ -0,0 +1,28 @@ +<!-- + -- Copyright (c) 2013 The Chromium Authors. All rights reserved. + -- Use of this source code is governed by a BSD-style license that can be + -- found in the LICENSE file. + --> + +<element name="kb-keyset" attributes="toKeyset" on-key-up="keyUp"> + <template> + <style> + @host { + * { + -webkit-box-orient: vertical; + -webkit-box-flex: 1; + display: -webkit-box; + } + } + </style> + <content></content> + </template> + <script> + Polymer.register(this, { + keyUp: function(event, detail) { + if (!detail.toKeyset) + detail.toKeyset = this.toKeyset; + } + }); + </script> +</element> diff --git a/ui/keyboard/resources/elements/kb-row.html b/ui/keyboard/resources/elements/kb-row.html new file mode 100644 index 0000000..21525b8 --- /dev/null +++ b/ui/keyboard/resources/elements/kb-row.html @@ -0,0 +1,28 @@ +<!--
+ -- Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ -- Use of this source code is governed by a BSD-style license that can be
+ -- found in the LICENSE file.
+ -->
+
+<element name="kb-row">
+ <template>
+ <style>
+ @host {
+ * {
+ -webkit-box-flex: 1;
+ display: -webkit-box;
+ text-align: center;
+ margin-right: 5px;
+ margin-top: 5px;
+ }
+ }
+ content::-webkit-distributed(kb-key) {
+ -webkit-flex: 1 auto;
+ }
+ </style>
+ <content select="*"></content>
+ </template>
+ <script>
+ Polymer.register(this);
+ </script>
+</element>
diff --git a/ui/keyboard/resources/images/ret.svg b/ui/keyboard/resources/images/ret.svg deleted file mode 100644 index 9f327f95..0000000 --- a/ui/keyboard/resources/images/ret.svg +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve"> -<g> - <g> - <path fill="#bababb" d="M22.75,31.432c-0.043,0-0.087-0.012-0.126-0.034l-6-3.5c-0.077-0.045-0.124-0.127-0.124-0.216 - s0.047-0.171,0.124-0.216l6-3.5c0.039-0.023,0.083-0.034,0.126-0.034c0.043,0,0.086,0.011,0.125,0.033 - C22.952,24.01,23,24.093,23,24.182v7c0,0.09-0.048,0.172-0.125,0.217C22.835,31.421,22.792,31.432,22.75,31.432L22.75,31.432z"/> - <path fill="#bababb" d="M22.75,24.182v7l-6-3.5L22.75,24.182 M22.75,23.682c-0.087,0-0.174,0.022-0.252,0.068l-6,3.5 - c-0.154,0.089-0.248,0.254-0.248,0.432s0.094,0.342,0.248,0.432l6,3.5c0.078,0.046,0.165,0.068,0.252,0.068 - c0.086,0,0.172-0.022,0.249-0.066c0.155-0.089,0.251-0.255,0.251-0.434v-7c0-0.179-0.096-0.344-0.251-0.434 - C22.921,23.704,22.835,23.682,22.75,23.682L22.75,23.682z"/> - </g> - <path fill="#bababb" d="M30.25,20.083v6.1h-10v3h11.5c0.828,0,1.5-0.672,1.5-1.5v-8.865L30.25,20.083z"/> -</g> -</svg> diff --git a/ui/keyboard/resources/images/shift-down.svg b/ui/keyboard/resources/images/shift-down.svg deleted file mode 100644 index 958aa29..0000000 --- a/ui/keyboard/resources/images/shift-down.svg +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="50px" height="50px" viewBox="10 10 30 30"> -<!-- TODO(fsamuel): remove the width and height workaround above after fixing SVG bug --> -<g> - <path fill="#e0e0e0" d="M23,29.25c-0.138,0-0.25-0.112-0.25-0.25v-2.75H20c-0.101,0-0.192-0.061-0.231-0.154 - s-0.017-0.201,0.054-0.272l5-5c0.049-0.049,0.113-0.073,0.177-0.073s0.128,0.024,0.177,0.073l5,5 - c0.071,0.071,0.093,0.179,0.055,0.272c-0.039,0.093-0.13,0.154-0.231,0.154h-2.75V29c0,0.138-0.112,0.25-0.25,0.25H23z"/> - <path fill="#e0e0e0" d="M25,21l5,5h-3v3h-4v-3h-3L25,21 M25,20.5c-0.128,0-0.256,0.049-0.354,0.146l-5,5 - c-0.143,0.143-0.186,0.358-0.108,0.545C19.615,26.377,19.797,26.5,20,26.5h2.5V29c0,0.276,0.224,0.5,0.5,0.5h4 - c0.276,0,0.5-0.224,0.5-0.5v-2.5H30c0.202,0,0.385-0.122,0.462-0.309c0.077-0.187,0.034-0.402-0.108-0.545l-5-5 - C25.255,20.548,25.127,20.5,25,20.5L25,20.5z"/> -</g> -</svg> diff --git a/ui/keyboard/resources/images/shift.svg b/ui/keyboard/resources/images/shift.svg deleted file mode 100644 index 08d8c8a..0000000 --- a/ui/keyboard/resources/images/shift.svg +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="50px" height="50px" viewBox="10 10 30 30"> -<!-- TODO(fsamuel): remove the width and height workaround above after fixing SVG bug --> -<g> - <path fill="#bababb" d="M23,29.25c-0.138,0-0.25-0.112-0.25-0.25v-2.75H20c-0.101,0-0.192-0.061-0.231-0.154 - s-0.017-0.201,0.054-0.272l5-5c0.049-0.049,0.113-0.073,0.177-0.073s0.128,0.024,0.177,0.073l5,5 - c0.071,0.071,0.093,0.179,0.055,0.272c-0.039,0.093-0.13,0.154-0.231,0.154h-2.75V29c0,0.138-0.112,0.25-0.25,0.25H23z"/> - <path fill="#bababb" d="M25,21l5,5h-3v3h-4v-3h-3L25,21 M25,20.5c-0.128,0-0.256,0.049-0.354,0.146l-5,5 - c-0.143,0.143-0.186,0.358-0.108,0.545C19.615,26.377,19.797,26.5,20,26.5h2.5V29c0,0.276,0.224,0.5,0.5,0.5h4 - c0.276,0,0.5-0.224,0.5-0.5v-2.5H30c0.202,0,0.385-0.122,0.462-0.309c0.077-0.187,0.034-0.402-0.108-0.545l-5-5 - C25.255,20.548,25.127,20.5,25,20.5L25,20.5z"/> -</g> -</svg> diff --git a/ui/keyboard/resources/images/tab.svg b/ui/keyboard/resources/images/tab.svg deleted file mode 100644 index 774e306..0000000 --- a/ui/keyboard/resources/images/tab.svg +++ /dev/null @@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="100%" height="100%" viewBox="5 5 40 40" enable-background="new" xml:space="preserve"> -<g> - <line fill="none" stroke="#bababb" stroke-width="1.7" stroke-linecap="round" x1="36.377" y1="20.5" x2="36.377" y2="29.5"/> - <g> - <path fill="#bababb" d="M27.377,28.75c-0.043,0-0.086-0.011-0.125-0.033c-0.077-0.045-0.125-0.127-0.125-0.217v-7 - c0-0.089,0.048-0.172,0.125-0.217c0.039-0.022,0.082-0.033,0.125-0.033c0.044,0,0.087,0.011,0.126,0.034l6,3.5 - c0.077,0.045,0.124,0.127,0.124,0.216s-0.047,0.171-0.124,0.216l-6,3.5C27.464,28.738,27.421,28.75,27.377,28.75L27.377,28.75z"/> - </g> - <polygon fill="#bababb" points="14.888,23.5 13.623,26.5 29.877,26.5 29.877,23.5 "/> -</g> -</svg> diff --git a/ui/keyboard/resources/index.html b/ui/keyboard/resources/index.html index fd05578..e00d88e 100644 --- a/ui/keyboard/resources/index.html +++ b/ui/keyboard/resources/index.html @@ -1,11 +1,26 @@ <!DOCTYPE HTML> +<!-- + -- Copyright (c) 2013 The Chromium Authors. All rights reserved. + -- Use of this source code is governed by a BSD-style license that can be + -- found in the LICENSE file. + --> + <html> <head> + <meta charset="UTF-8"> <link rel="stylesheet" href="main.css"> + <script src="constants.js"></script> + <script src="polymer.min.js"></script> <script src="api_adapter.js"></script> - <script src="common.js"></script> - <script src="layout_us.js"></script> + <script src="voice_input.js"></script> + <link rel="import" href="elements/kb-key.html"> + <link rel="import" href="elements/kb-row.html"> + <link rel="import" href="elements/kb-keyset.html"> + <link rel="import" href="elements/kb-keyboard.html"> + <link id="keysets" rel="import" href="keysets.html"> <script src="main.js"></script> </head> - <body id="b"></body> + <body> + <kb-keyboard id="keyboard" touch-action="none" keyset="lower"></kb-keyboard> + </body> </html> diff --git a/ui/keyboard/resources/keysets.html b/ui/keyboard/resources/keysets.html new file mode 100644 index 0000000..256cbbd --- /dev/null +++ b/ui/keyboard/resources/keysets.html @@ -0,0 +1,131 @@ +<!-- + -- Copyright (c) 2013 The Chromium Authors. All rights reserved. + -- Use of this source code is governed by a BSD-style license that can be + -- found in the LICENSE file. + --> + +<template> + <kb-keyset id="upper" toKeyset="lower"> + <kb-row> + <kb-key class="tab dark" char="Tab">tab</kb-key><kb-key>Q</kb-key> + <kb-key>W</kb-key><kb-key>E</kb-key><kb-key>R</kb-key><kb-key>T</kb-key> + <kb-key>Y</kb-key><kb-key>U</kb-key><kb-key>I</kb-key><kb-key>O</kb-key> + <kb-key>P</kb-key> + <kb-key class="backspace dark" char="Backspace" repeat>backspace</kb-key> + </kb-row> + <kb-row> + <kb-key class="symbol dark" toKeyset="symbol" char="Invalid">#123</kb-key> + <kb-key>A</kb-key><kb-key>S</kb-key><kb-key>D</kb-key><kb-key>F</kb-key> + <kb-key>G</kb-key><kb-key>H</kb-key><kb-key>J</kb-key><kb-key>K</kb-key> + <kb-key>L</kb-key><kb-key>\</kb-key> + <kb-key class='return dark' char="Enter">enter</kb-key> + </kb-row> + <kb-row> + <kb-key class="left-shift dark" toKeyset="lower" char="Invalid">shift</kb-key> + <kb-key>Z</kb-key><kb-key>X</kb-key><kb-key>C</kb-key><kb-key>V</kb-key> + <kb-key>B</kb-key><kb-key>N</kb-key><kb-key>M</kb-key><kb-key>@</kb-key> + <kb-key>!</kb-key><kb-key>/</kb-key> + <kb-key class="right-shift dark" toKeyset="lower" char="Invalid">shift</kb-key> + </kb-row> + <kb-row> + <kb-key class="mic dark" char="Mic"></kb-key> + <kb-key class="dark">.com</kb-key> + <kb-key char="Spacebar" class="space dark" toKeyset="upper"></kb-key> + <kb-key class="dark">@</kb-key> + <kb-key class="hide dark"></kb-key> + </kb-row> + </kb-keyset> + + <kb-keyset id="lower"> + <kb-row> + <kb-key class="tab dark" char="Tab">tab</kb-key><kb-key>q</kb-key> + <kb-key>w</kb-key><kb-key>e</kb-key><kb-key>r</kb-key><kb-key>t</kb-key> + <kb-key>y</kb-key><kb-key>u</kb-key><kb-key>i</kb-key><kb-key>o</kb-key> + <kb-key>p</kb-key> + <kb-key class="backspace dark" char="Backspace" repeat>backspace</kb-key> + </kb-row> + <kb-row> + <kb-key class="symbol dark" toKeyset="symbol" char="Invalid">#123</kb-key> + <kb-key>a</kb-key><kb-key>s</kb-key><kb-key>d</kb-key><kb-key>f</kb-key> + <kb-key>g</kb-key><kb-key>h</kb-key><kb-key>j</kb-key><kb-key>k</kb-key> + <kb-key>l</kb-key><kb-key>;</kb-key> + <kb-key class='return dark' char="Enter">enter</kb-key> + </kb-row> + <kb-row> + <kb-key class="left-shift dark" toKeyset="upper" char="Invalid">shift</kb-key> + <kb-key>z</kb-key><kb-key>x</kb-key><kb-key>c</kb-key><kb-key>v</kb-key> + <kb-key>b</kb-key><kb-key>n</kb-key><kb-key>m</kb-key><kb-key>,</kb-key> + <kb-key>.</kb-key><kb-key>?</kb-key> + <kb-key class="right-shift dark" toKeyset="upper" char="Invalid">shift</kb-key> + </kb-row> + <kb-row> + <kb-key class="mic dark" char="Mic"></kb-key> + <kb-key class="dark">.com</kb-key> + <kb-key class="space dark" char="Spacebar"></kb-key> + <kb-key class="dark">@</kb-key> + <kb-key class="hide dark"></kb-key> + </kb-row> + </kb-keyset> + + <kb-keyset id="symbol"> + <kb-row> + <kb-key class="tab dark" char="Tab">tab</kb-key><kb-key>1</kb-key> + <kb-key>2</kb-key><kb-key>3</kb-key><kb-key>4</kb-key><kb-key>5</kb-key> + <kb-key>6</kb-key><kb-key>7</kb-key><kb-key>8</kb-key><kb-key>9</kb-key> + <kb-key>0</kb-key> + <kb-key class="backspace dark" char="Backspace" repeat>backspace</kb-key> + </kb-row> + <kb-row> + <kb-key class="symbol dark" toKeyset="lower" char="Invalid">abc</kb-key> + <kb-key>!</kb-key><kb-key>@</kb-key><kb-key>#</kb-key><kb-key>$</kb-key> + <kb-key>%</kb-key><kb-key>^</kb-key><kb-key>&</kb-key><kb-key>*</kb-key> + <kb-key>(</kb-key><kb-key>)</kb-key> + <kb-key class='return dark' char="Enter">enter</kb-key> + </kb-row> + <kb-row> + <kb-key class="left-more dark" toKeyset="more" char="Invalid">more</kb-key> + <kb-key>/</kb-key><kb-key>-</kb-key><kb-key>'</kb-key><kb-key>"</kb-key> + <kb-key>:</kb-key><kb-key>;</kb-key><kb-key>_</kb-key><kb-key>,</kb-key> + <kb-key>.</kb-key><kb-key>?</kb-key> + <kb-key class="right-more dark" toKeyset="more" char="Invalid">more</kb-key> + </kb-row> + <kb-row> + <kb-key class="mic dark" char="Mic"></kb-key> + <kb-key class="dark">.com</kb-key> + <kb-key class="space dark" char="Spacebar"></kb-key> + <kb-key class="dark">@</kb-key> + <kb-key class="hide dark"></kb-key> + </kb-row> + </kb-keyset> + + <kb-keyset id="more"> + <kb-row> + <kb-key class="tab dark" char="Tab">tab</kb-key><kb-key>`</kb-key> + <kb-key>~</kb-key><kb-key><</kb-key><kb-key>></kb-key> + <kb-key>[</kb-key><kb-key>]</kb-key><kb-key>{</kb-key><kb-key>}</kb-key> + <kb-key>\</kb-key><kb-key>|</kb-key> + <kb-key class="backspace dark" char="Backspace" repeat>backspace</kb-key> + </kb-row> + <kb-row> + <kb-key class="symbol dark" toKeyset="lower" char="Invalid">abc</kb-key> + <kb-key>+</kb-key><kb-key>=</kb-key><kb-key></kb-key><kb-key></kb-key> + <kb-key></kb-key><kb-key></kb-key><kb-key></kb-key><kb-key></kb-key> + <kb-key></kb-key><kb-key></kb-key> + <kb-key class='return dark' char="Enter">enter</kb-key> + </kb-row> + <kb-row> + <kb-key class="left-more dark" toKeyset="symbol" char="Invalid">#123</kb-key> + <kb-key></kb-key><kb-key></kb-key><kb-key></kb-key><kb-key></kb-key> + <kb-key></kb-key><kb-key></kb-key><kb-key></kb-key><kb-key></kb-key> + <kb-key></kb-key><kb-key></kb-key> + <kb-key class="right-more dark" toKeyset="symbol" char="Invalid">#123</kb-key> + </kb-row> + <kb-row> + <kb-key class="mic dark" char="Mic"></kb-key> + <kb-key class="dark">.com</kb-key> + <kb-key class="space dark" char="Spacebar"></kb-key> + <kb-key class="dark">@</kb-key> + <kb-key class="hide dark"></kb-key> + </kb-row> + </kb-keyset> +</template> diff --git a/ui/keyboard/resources/layout_us.js b/ui/keyboard/resources/layout_us.js deleted file mode 100644 index 83a0439..0000000 --- a/ui/keyboard/resources/layout_us.js +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview A simple English virtual keyboard implementation. - */ - -/** - * All keys for the rows of the keyboard. - * NOTE: every row below should have an aspect of 12.6. - * @type {Array.<Array.<BaseKey>>} - */ -var KEYS_US = [ - [ - new SvgKey('tab', 'Tab'), - new Key(C('q'), C('Q'), C('1'), C('`')), - new Key(C('w'), C('W'), C('2'), C('~')), - new Key(C('e'), C('E'), C('3'), C('<', 'LessThan')), - new Key(C('r'), C('R'), C('4'), C('>', 'GreaterThan')), - new Key(C('t'), C('T'), C('5'), C('[')), - new Key(C('y'), C('Y'), C('6'), C(']')), - new Key(C('u'), C('U'), C('7'), C('{')), - new Key(C('i'), C('I'), C('8'), C('}')), - new Key(C('o'), C('O'), C('9'), C('\\')), - new Key(C('p'), C('P'), C('0'), C('|')), - new SvgKey('backspace', 'Backspace', true /* repeat */) - ], - [ - new SymbolKey(), - new Key(C('a'), C('A'), C('!'), C('+')), - new Key(C('s'), C('S'), C('@'), C('=')), - new Key(C('d'), C('D'), C('#'), C(' ')), - new Key(C('f'), C('F'), C('$'), C(' ')), - new Key(C('g'), C('G'), C('%'), C(' ')), - new Key(C('h'), C('H'), C('^'), C(' ')), - new Key(C('j'), C('J'), C('&', 'Ampersand'), C(' ')), - new Key(C('k'), C('K'), C('*'), C(' ')), - new Key(C('l'), C('L'), C('('), C(' ')), - new Key(C(';'), C('\''), C(')'), C(' ')), - new SvgKey('return', 'Enter') - ], - [ - new ShiftKey('left-shift'), - new Key(C('z'), C('Z'), C('/'), C(' ')), - new Key(C('x'), C('X'), C('-'), C(' ')), - new Key(C('c'), C('C'), C('\''), C(' ')), - new Key(C('v'), C('V'), C('\"'), C(' ')), - new Key(C('b'), C('B'), C(':'), C(' ')), - new Key(C('n'), C('N'), C(';'), C(' ')), - new Key(C('m'), C('M'), C('_'), C(' ')), - new Key(C(','), C('@'), C(','), C(' ')), - new Key(C('.'), C('!'), C('.'), C(' ')), - new Key(C('?'), C('/'), C('?'), C(' ')), - new ShiftKey('right-shift') - ], - [ - new MicKey(), - new DotComKey(), - new SpecialKey('space', ' ', 'Spacebar'), - new SpecialKey('at', '@', '@'), - new HideKeyboardKey() - ] -]; - -// Add layout to KEYBOARDS, which is defined in common.js -KEYBOARDS['us'] = { - 'definition': KEYS_US, - 'aspect': 4.50 -}; diff --git a/ui/keyboard/resources/main.css b/ui/keyboard/resources/main.css index 0e96e41..172b9f3 100644 --- a/ui/keyboard/resources/main.css +++ b/ui/keyboard/resources/main.css @@ -14,111 +14,31 @@ body { padding: 0; } -div.main { +kb-keyboard { -webkit-box-orient: vertical; display: -webkit-box; max-width: 1280px; + width: 1280px; } -div.keyboard { - -webkit-box-flex: 1; - display: -webkit-box; - margin: 0 auto; - text-align: center; -} - -div.rows { - -webkit-box-flex: 1; - -webkit-box-orient: vertical; - display: -webkit-box; - margin-bottom: 5px; - text-align: center; -} - -div.row { - -webkit-box-flex: 1; - display: -webkit-box; - margin-right: 5px; - margin-top: 5px; -} - -div.row > div { - -webkit-box-flex: 1; - display: -webkit-box; -} - -.panel { - border: 0; - clear: both; - margin-left: 5px; - text-align: left; -} - -.backspace > div { - background-image: url('images/del.svg'); -} - -.tab > div { - background-image: url('images/tab.svg'); -} - -.return > div { - background-image: url('images/ret.svg'); -} - -.mic > div { - background-image: url('images/mic.svg'); -} - -.mic.start > div { - background-image: url('images/mic-green.svg'); -} - -.button { - background: -webkit-linear-gradient(rgb(90, 97, 111), rgb(80, 86, 98)); -} -.button:active { - background: -webkit-linear-gradient(rgb(80, 86, 98), rgb(90, 97, 111)); -} - -.auxiliary:active { - background: -webkit-linear-gradient(rgb(90, 97, 111), rgb(80, 86, 98)); -} - -.key { - -webkit-box-flex: 1; +kb-key { background-color: #444444; border-top: 1px solid #666666; border-radius: 3px; - /* Reserving equivalent space to .key:active so - keys don't shift when selected. */ - /* Do not use box shadow until performance improves - * http://code.google.com/p/chromium/issues/detail?id=99045 - box-shadow: 0px 1px 1px #000; - */ color: #ffffff; - display: -webkit-box; font-family: sans-serif; font-weight: 100; margin-left: 5px; - position: relative; } -.key.dark { +kb-key.dark { background-color: #333333; } -.key > div { - bottom: 0; - left: 0; - margin: auto; - position: absolute; - right: 0; - top: 0; -} - -.key:active { - background-color: #acacac; +#upper .left-shift, +#upper .right-shift, +.active { + background-color: #acacac !important; border-top: 1px solid rgba(125,125,125,0.5); /* Do not use box shadow until performance improves * http://code.google.com/p/chromium/issues/detail?id=99045 @@ -126,36 +46,6 @@ div.row > div { */ } -div.moddown.dark { - background-color: #acacac; - border-color: rgb(48, 74, 155); -} - -.image-key { - background-position: center center; - background-repeat: no-repeat; - background-size: contain; - height: 100%; - width: 100%; -} - -.text-key { - height: 1.2em; -} - - -.shift > div.image-key { - background-image: url('images/shift.svg'); -} - -.moddown.shift > div.image-key { - background-image: url('images/shift-down.svg'); -} - -.hide > div { - background-image: url('images/keyboard.svg'); -} - .at, .com, .comma, @@ -163,34 +53,56 @@ div.moddown.dark { .mic, .period, .tab { - -webkit-box-flex: 1.3; + -webkit-box-flex: 1.3 !important; } .symbol, .return { - -webkit-box-flex: 1.5; + -webkit-box-flex: 1.5 !important; } .backspace { - -webkit-box-flex: 1.7; + -webkit-box-flex: 1.7 !important; } -.left-shift { - -webkit-box-flex: 1.4; +.left-shift, +.left-more { + -webkit-box-flex: 1.4 !important; } -.right-shift { - -webkit-box-flex: 1.6; +.right-shift, +.right-more { + -webkit-box-flex: 1.6 !important; } .space { - -webkit-box-flex: 4.8; + -webkit-box-flex: 4.8 !important; } .bar { - -webkit-box-flex: 0.6; + -webkit-box-flex: 0.6 !important; +} + +.backspace, +.tab, +.return, +.left-shift, +.right-shift, +.left-more, +.right-more, +.symbol, +.moddown.shift { + font-size: 80%; } -.nodisplay { - display: none; +.mic { + background-image: url('images/mic.svg'); +} + +.audio .mic { + background-image: url('images/mic-green.svg'); +} + +.hide { + background-image: url('images/keyboard.svg'); } diff --git a/ui/keyboard/resources/main.js b/ui/keyboard/resources/main.js index a628cad..9ae319b 100644 --- a/ui/keyboard/resources/main.js +++ b/ui/keyboard/resources/main.js @@ -1,192 +1,39 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -/** - * @fileoverview A simple virtual keyboard implementation. - */ - -/** - * The ratio of the row height to the font size. - * @type {number} - */ -/** @const */ var kFontSizeRatio = 3.5; - -/** - * Alias for document.getElementById. - * @param {string} id The ID of the element to find. - * @return {HTMLElement} The found element or null if not found. - */ -function $(id) { - return document.getElementById(id); -} - -/** - * Return the id attribute of the keyboard element for the given layout. - * @param {string} layout The keyboard layout. - * @return {string} The id attribute of the keyboard element. - */ -function getKeyboardId(layout) { - return 'keyboard_' + layout; -} - -/** - * Return the aspect ratio of the current keyboard. - * @return {number} The aspect ratio of the current keyboard. - */ -function getKeyboardAspect() { - return KEYBOARDS[currentKeyboardLayout]['aspect']; -} - -/** - * Calculate the height of the keyboard based on the size of the page. - * @return {number} The height of the keyboard in pixels. - */ -function getKeyboardHeight() { +var onResize = function() { var x = window.innerWidth; var y = window.innerHeight; - return (x > getKeyboardAspect() * y) ? - y : Math.floor(x / getKeyboardAspect()); -} - -/** - * Create a DOM of the keyboard rows for the given keyboard layout. - * Do nothing if the DOM is already created. - * @param {string} layout The keyboard layout for which rows are created. - * @param {Element} element The DOM Element to which rows are appended. - * @param {boolean} autoPadding True if padding needs to be added to both side - * of the rows that have less keys. - */ -function initRows(layout, element, autoPadding) { - var keyboard = KEYBOARDS[layout]; - if ('rows' in keyboard) { - return; - } - var def = keyboard['definition']; - var rows = []; - for (var i = 0; i < def.length; ++i) { - rows.push(new Row(i, def[i])); - } - keyboard['rows'] = rows; - - var maxRowLength = -1; - for (var i = 0; i < rows.length; ++i) { - if (rows[i].length > maxRowLength) { - maxRowLength = rows[i].length; - } - } - - // A div element which holds rows for the layout. - var rowsDiv = document.createElement('div'); - rowsDiv.className = 'rows'; - for (var i = 0; i < rows.length; ++i) { - var rowDiv = rows[i].makeDOM(); - if (autoPadding && rows[i].length < maxRowLength) { - var padding = 50 * (maxRowLength - rows[i].length) / maxRowLength; - rowDiv.style.paddingLeft = padding + '%'; - rowDiv.style.paddingRight = padding + '%'; - } - rowsDiv.appendChild(rowDiv); - rows[i].showMode(currentMode); - } - keyboard['rowsDiv'] = rowsDiv; - element.appendChild(rowsDiv); -} - -/** - * Create a DOM of the keyboard for the given keyboard layout. - * Do nothing if the DOM is already created. - * @param {string} layout The keyboard layout for which keyboard is created. - * @param {Element} element The DOM Element to which keyboard is appended. - */ -function initKeyboard(layout, element) { - var keyboard = KEYBOARDS[layout]; - if (!keyboard || keyboard['keyboardDiv']) { - return; - } - var keyboardDiv = document.createElement('div'); - keyboardDiv.id = getKeyboardId(layout); - keyboardDiv.className = 'keyboard'; - initRows(layout, keyboardDiv); - keyboard['keyboardDiv'] = keyboardDiv; - window.onresize(); - element.appendChild(keyboardDiv); -} - -/** - * Resize the keyboard according to the new window size. - */ -window.onresize = function() { - var keyboardDiv = KEYBOARDS[currentKeyboardLayout]['keyboardDiv']; - var height = getKeyboardHeight(); - keyboardDiv.style.height = height + 'px'; - var mainDiv = $('main'); - mainDiv.style.width = Math.floor(getKeyboardAspect() * height) + 'px'; - var rowsLength = KEYBOARDS[currentKeyboardLayout]['rows'].length; - keyboardDiv.style.fontSize = (height / kFontSizeRatio / rowsLength) + 'px'; + var height = (x > ASPECT_RATIO * y) ? y : Math.floor(x / ASPECT_RATIO); + keyboard.style.height = height + 'px'; + keyboard.style.width = Math.floor(ASPECT_RATIO * height) + 'px'; + keyboard.style.fontSize = (height / FONT_SIZE_RATIO / ROW_LENGTH) + 'px'; }; /** - * Init the keyboard. + * Send the given key to chrome. */ -var mainDiv = null; +function sendKey(key) { + var keyIdentifier = key; -/** - * Initialize keyboard. - */ -window.onload = function() { - var body = $('b'); - - // Catch all unhandled touch events and prevent default, to prevent the - // keyboard from responding to gestures like double tap. - function disableGestures(evt) { - evt.preventDefault(); + // Fix up some keys to their respective identifiers for convenience. + if (keyIdentifier == ' ') { + keyIdentifier = 'Spacebar'; } - body.addEventListener('touchstart', disableGestures); - body.addEventListener('touchmove', disableGestures); - body.addEventListener('touchend', disableGestures); - mainDiv = document.createElement('div'); - mainDiv.className = 'main'; - mainDiv.id = 'main'; - body.appendChild(mainDiv); + var keyEvent = { + keyIdentifier: keyIdentifier + }; - initKeyboard(currentKeyboardLayout, mainDiv); - - window.onhashchange(); + sendKeyEvent(keyEvent); }; -/** - * Switch the keyboard layout based on the current URL hash. - */ -window.onhashchange = function() { - var oldLayout = currentKeyboardLayout; - var newLayout = location.hash.replace(/^#/, ''); - if (oldLayout == newLayout) { - return; - } - - if (KEYBOARDS[newLayout] === undefined) { - // Unsupported layout. - newLayout = 'us'; - } - currentKeyboardLayout = newLayout; +addEventListener('WebComponentsReady', function() { + keyboard.appendChild( + keysets.content.body.firstElementChild.createInstance()); +}); - var mainDiv = $('main'); - initKeyboard(currentKeyboardLayout, mainDiv); +addEventListener('resize', onResize); - [newLayout, oldLayout].forEach(function(layout) { - var visible = (layout == newLayout); - var keyboardDiv = KEYBOARDS[layout]['keyboardDiv']; - keyboardDiv.className = visible ? 'keyboard' : 'nodisplay'; - var canvas = KEYBOARDS[layout]['canvas']; - if (canvas !== undefined) { - if (!visible) { - canvas.clear(); - } - } - if (visible) { - window.onresize(); - } - }); -}; +addEventListener('load', onResize); diff --git a/ui/keyboard/resources/manifest.json b/ui/keyboard/resources/manifest.json index f07121c..93d4a8f 100644 --- a/ui/keyboard/resources/manifest.json +++ b/ui/keyboard/resources/manifest.json @@ -11,5 +11,6 @@ "permissions": [ "audioCapture", "experimental" - ] + ], + "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'" } diff --git a/ui/keyboard/resources/polymer.min.js b/ui/keyboard/resources/polymer.min.js new file mode 100644 index 0000000..915f7d9 --- /dev/null +++ b/ui/keyboard/resources/polymer.min.js @@ -0,0 +1,5 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +<include src="../../../third_party/polymer/polymer.min.js"></include> diff --git a/ui/keyboard/resources/voice_input.js b/ui/keyboard/resources/voice_input.js new file mode 100644 index 0000000..bb8d9f7 --- /dev/null +++ b/ui/keyboard/resources/voice_input.js @@ -0,0 +1,71 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +function VoiceInput(keyboard) { + this.finaResult_ = null; + this.recognizing_ = false; + this.keyboard_ = keyboard; + this.recognition_ = new webkitSpeechRecognition(); + this.recognition_.onstart = this.onStartHandler.bind(this); + this.recognition_.onresult = this.onResultHandler.bind(this); + this.recognition_.onerror = this.onErrorHandler.bind(this); + this.recognition_.onend = this.onEndHandler.bind(this); +}; + +VoiceInput.prototype = { + /** + * Event handler for mouse/touch down events. + */ + onDown: function() { + if (this.recognizing_) { + this.recognition_.stop(); + return; + } + this.recognition_.start(); + }, + + /** + * Speech recognition started. Change mic key's icon. + */ + onStartHandler: function() { + this.recognizing_ = true; + this.finalResult_ = ''; + if (!this.keyboard_.classList.contains('audio')) + this.keyboard_.classList.add('audio'); + }, + + /** + * Speech recognizer returns a result. + * @param{Event} e The SpeechRecognition event that is raised each time + * there + * are any changes to interim or final results. + */ + onResultHandler: function(e) { + for (var i = e.resultIndex; i < e.results.length; i++) { + if (e.results[i].isFinal) + this.finalResult_ = e.results[i][0].transcript; + } + for (var i = 0; i < this.finalResult_.length; i++) { + sendKey(this.finalResult_.charAt(i)); + } + }, + + /** + * Speech recognizer returns an error. + * @param{Event} e The SpeechRecognitionError event that is raised each time + * there is an error. + */ + onErrorHandler: function(e) { + console.error('error code = ' + e.error); + }, + + /** + * Speech recognition ended. Reset mic key's icon. + */ + onEndHandler: function() { + if (this.keyboard_.classList.contains('audio')) + this.keyboard_.classList.remove('audio'); + this.recognizing_ = false; + } +}; diff --git a/ui/keyboard/resources/webui/constants.js b/ui/keyboard/resources/webui/constants.js new file mode 100644 index 0000000..ea620c6 --- /dev/null +++ b/ui/keyboard/resources/webui/constants.js @@ -0,0 +1,26 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +/** + * Aspect ratio of keyboard. + * @type {number} + */ +var ASPECT_RATIO = 2.0; + +/** + * Ratio of key height and font size. + * @type {number} + */ +var FONT_SIZE_RATIO = 3.5; + +/** + * The number of rows in each keyset. + * @type {number} + */ +// TODO(bshe): The number of rows should equal to the number of kb-row elements +// in kb-keyset. Remove this variable once figure out how to calculate the +// number from keysets. + +var ROW_LENGTH = 4; diff --git a/ui/keyboard/resources/webui/keysets.html b/ui/keyboard/resources/webui/keysets.html new file mode 100644 index 0000000..91c7bf2 --- /dev/null +++ b/ui/keyboard/resources/webui/keysets.html @@ -0,0 +1,119 @@ +<!-- + -- Copyright (c) 2013 The Chromium Authors. All rights reserved. + -- Use of this source code is governed by a BSD-style license that can be + -- found in the LICENSE file. + --> + +<template> + <kb-keyset id="upper" toKeyset="lower"> + <kb-row> + <kb-key>Q</kb-key><kb-key>W</kb-key><kb-key>E</kb-key><kb-key>R</kb-key> + <kb-key>T</kb-key><kb-key>Y</kb-key><kb-key>U</kb-key><kb-key>I</kb-key> + <kb-key>O</kb-key><kb-key>P</kb-key> + </kb-row> + <kb-row> + <kb-key class="tab dark" char="Tab">tab</kb-key> + <kb-key>A</kb-key><kb-key>S</kb-key><kb-key>D</kb-key><kb-key>F</kb-key> + <kb-key>G</kb-key><kb-key>H</kb-key><kb-key>J</kb-key><kb-key>K</kb-key> + <kb-key>L</kb-key> + </kb-row> + <kb-row> + <kb-key class="left-shift dark" toKeyset="lower" char="Invalid">shift</kb-key> + <kb-key>Z</kb-key><kb-key>X</kb-key><kb-key>C</kb-key><kb-key>V</kb-key> + <kb-key>B</kb-key><kb-key>N</kb-key><kb-key>M</kb-key> + <kb-key class="backspace dark" char="Backspace" repeat>backspace</kb-key> + </kb-row> + <kb-row> + <kb-key class="mic dark" char="Mic"></kb-key> + <kb-key class="symbol dark" toKeyset="symbol" char="Invalid">#123</kb-key> + <kb-key class="dark">.com</kb-key> + <kb-key class="space dark" char="Spacebar"></kb-key> + <kb-key class="dark">@</kb-key> + <kb-key class='return dark' char="Enter">enter</kb-key> + </kb-row> + </kb-keyset> + + <kb-keyset id="lower"> + <kb-row> + <kb-key>q</kb-key><kb-key>w</kb-key><kb-key>e</kb-key><kb-key>r</kb-key> + <kb-key>t</kb-key><kb-key>y</kb-key><kb-key>u</kb-key><kb-key>i</kb-key> + <kb-key>o</kb-key><kb-key>p</kb-key> + </kb-row> + <kb-row> + <kb-key class="tab dark" char="Tab">tab</kb-key> + <kb-key>a</kb-key><kb-key>s</kb-key><kb-key>d</kb-key><kb-key>f</kb-key> + <kb-key>g</kb-key><kb-key>h</kb-key><kb-key>j</kb-key><kb-key>k</kb-key> + <kb-key>l</kb-key> + </kb-row> + <kb-row> + <kb-key class="left-shift dark" toKeyset="upper" char="Invalid">shift</kb-key> + <kb-key>z</kb-key><kb-key>x</kb-key><kb-key>c</kb-key><kb-key>v</kb-key> + <kb-key>b</kb-key><kb-key>n</kb-key><kb-key>m</kb-key> + <kb-key class="backspace dark" char="Backspace" repeat>backspace</kb-key> + </kb-row> + <kb-row> + <kb-key class="mic dark" char="Mic"></kb-key> + <kb-key class="symbol dark" toKeyset="symbol" char="Invalid">#123</kb-key> + <kb-key class="dark">.com</kb-key> + <kb-key class="space dark" char="Spacebar"></kb-key> + <kb-key class="dark">@</kb-key> + <kb-key class='return dark' char="Enter">enter</kb-key> + </kb-row> + </kb-keyset> + + <kb-keyset id="symbol"> + <kb-row> + <kb-key>1</kb-key><kb-key>2</kb-key><kb-key>3</kb-key><kb-key>4</kb-key> + <kb-key>5</kb-key><kb-key>6</kb-key><kb-key>7</kb-key><kb-key>8</kb-key> + <kb-key>9</kb-key><kb-key>0</kb-key> + </kb-row> + <kb-row> + <kb-key class="tab dark" char="Tab">tab</kb-key> + <kb-key>!</kb-key><kb-key>@</kb-key><kb-key>#</kb-key><kb-key>$</kb-key> + <kb-key>%</kb-key><kb-key>^</kb-key><kb-key>&</kb-key><kb-key>*</kb-key> + <kb-key>(</kb-key> + </kb-row> + <kb-row> + <kb-key class="left-more dark" toKeyset="more" char="Invalid">more</kb-key> + <kb-key>)</kb-key><kb-key>/</kb-key><kb-key>-</kb-key><kb-key>'</kb-key> + <kb-key>"</kb-key><kb-key>:</kb-key><kb-key>;</kb-key> + <kb-key class="backspace dark" char="Backspace" repeat>backspace</kb-key> + </kb-row> + <kb-row> + <kb-key class="mic dark" char="Mic"></kb-key> + <kb-key class="symbol dark" toKeyset="lower" char="Invalid">abc</kb-key> + <kb-key class="dark">.com</kb-key> + <kb-key class="space dark" char="Spacebar"></kb-key> + <kb-key class="dark">@</kb-key> + <kb-key class='return dark' char="Enter">enter</kb-key> + </kb-row> + </kb-keyset> + + <kb-keyset id="more"> + <kb-row> + <kb-key>_</kb-key><kb-key>`</kb-key><kb-key>~</kb-key> + <kb-key><</kb-key><kb-key>></kb-key><kb-key>[</kb-key> + <kb-key>]</kb-key><kb-key>{</kb-key><kb-key>}</kb-key><kb-key>\</kb-key> + </kb-row> + <kb-row> + <kb-key class="tab dark" char="Tab">tab</kb-key> + <kb-key>|</kb-key><kb-key>+</kb-key><kb-key>=</kb-key><kb-key></kb-key> + <kb-key></kb-key><kb-key></kb-key><kb-key></kb-key><kb-key></kb-key> + <kb-key></kb-key> + </kb-row> + <kb-row> + <kb-key class="left-more dark" toKeyset="symbol" char="Invalid">#123</kb-key> + <kb-key></kb-key><kb-key></kb-key><kb-key></kb-key><kb-key></kb-key> + <kb-key></kb-key><kb-key></kb-key><kb-key></kb-key> + <kb-key class="backspace dark" char="Backspace" repeat>backspace</kb-key> + </kb-row> + <kb-row> + <kb-key class="mic dark" char="Mic"></kb-key> + <kb-key class="symbol dark" toKeyset="lower" char="Invalid">abc</kb-key> + <kb-key class="dark">.com</kb-key> + <kb-key class="space dark" char="Spacebar"></kb-key> + <kb-key class="dark">@</kb-key> + <kb-key class='return dark' char="Enter">enter</kb-key> + </kb-row> + </kb-keyset> +</template> diff --git a/ui/keyboard/resources/webui/layout_us.js b/ui/keyboard/resources/webui/layout_us.js deleted file mode 100644 index 6c9565c..0000000 --- a/ui/keyboard/resources/webui/layout_us.js +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview A simple English virtual keyboard implementation. - */ - -/** - * All keys for the rows of the keyboard. - * NOTE: every row below should have an aspect of 12.6. - * @type {Array.<Array.<BaseKey>>} - */ -var KEYS_US = [ - [ - new Key(C('q'), C('Q'), C('1'), C('`')), - new Key(C('w'), C('W'), C('2'), C('~')), - new Key(C('e'), C('E'), C('3'), C('<', 'LessThan')), - new Key(C('r'), C('R'), C('4'), C('>', 'GreaterThan')), - new Key(C('t'), C('T'), C('5'), C('[')), - new Key(C('y'), C('Y'), C('6'), C(']')), - new Key(C('u'), C('U'), C('7'), C('{')), - new Key(C('i'), C('I'), C('8'), C('}')), - new Key(C('o'), C('O'), C('9'), C('\'')), - new Key(C('p'), C('P'), C('0'), C('|')), - ], - [ - new SvgKey('tab', 'Tab'), - new Key(C('a'), C('A'), C('!'), C('+')), - new Key(C('s'), C('S'), C('@'), C('=')), - new Key(C('d'), C('D'), C('#'), C(' ')), - new Key(C('f'), C('F'), C('$'), C(' ')), - new Key(C('g'), C('G'), C('%'), C(' ')), - new Key(C('h'), C('H'), C('^'), C(' ')), - new Key(C('j'), C('J'), C('&', 'Ampersand'), C(' ')), - new Key(C('k'), C('K'), C('*'), C('#')), - new Key(C('l'), C('L'), C('('), C(' ')), - ], - [ - new ShiftKey('left_shift'), - new Key(C('z'), C('Z'), C('/'), C(' ')), - new Key(C('x'), C('X'), C('-'), C(' ')), - new Key(C('c'), C('C'), C('\''), C(' ')), - new Key(C('v'), C('V'), C('"'), C(' ')), - new Key(C('b'), C('B'), C(':'), C('.')), - new Key(C('n'), C('N'), C(';'), C(' ')), - new Key(C('m'), C('M'), C('_'), C(' ')), - new SvgKey('backspace', 'Backspace', true /* repeat */) - ], - [ - new MicKey(), - new SymbolKey(), - new SpecialKey('comma', ',', ','), - new SpecialKey('space', ' ', 'Spacebar'), - new SpecialKey('period', '.', '.'), - new SvgKey('return', 'Enter') - ] -]; - -// Add layout to KEYBOARDS, which is defined in common.js -KEYBOARDS['us'] = { - 'definition': KEYS_US, - 'aspect': 2.00, -}; diff --git a/ui/keyboard/resources/webui/main.css b/ui/keyboard/resources/webui/main.css index 0a5e3b5..66244b1 100644 --- a/ui/keyboard/resources/webui/main.css +++ b/ui/keyboard/resources/webui/main.css @@ -7,189 +7,96 @@ body { -webkit-box-pack: center; -webkit-user-select: none; - color: white; + background-color: #0b0b0b; display: -webkit-box; margin: 0; overflow: hidden; padding: 0; } -div.main { +kb-keyboard { -webkit-box-orient: vertical; - background: -webkit-linear-gradient(#bababa, #868686) no-repeat; display: -webkit-box; } -div.keyboard { - -webkit-box-flex: 1; - display: -webkit-box; - margin: 0 auto; - text-align: center; -} - -div.rows { - -webkit-box-flex: 1; - -webkit-box-orient: vertical; - display: -webkit-box; - margin-bottom: 3px; - text-align: center; -} - -div.row { - -webkit-box-flex: 1; - display: -webkit-box; - margin-right: 3px; - margin-top: 3px; -} - -div.row > div { - -webkit-box-flex: 1; - display: -webkit-box; -} - -.panel { - border: 0; - clear: both; - margin-left: 5px; - text-align: left; -} - -.backspace > div { - background-image: url('images/del.svg'); -} - -.tab > div { - background-image: url('images/tab.svg'); -} - -.return > div { - background-image: url('images/ret.svg'); -} - -.mic > div { - background-image: url('images/mic.svg'); -} - -.mic.start > div { - background-image: url('images/mic-green.svg'); -} - -.button { - background: -webkit-linear-gradient(rgb(90, 97, 111), rgb(80, 86, 98)); -} -.button:active { - background: -webkit-linear-gradient(rgb(80, 86, 98), rgb(90, 97, 111)); -} - -.auxiliary:active { - background: -webkit-linear-gradient(rgb(90, 97, 111), rgb(80, 86, 98)); -} - -.key { - -webkit-box-flex: 1; - background: -webkit-linear-gradient(#fff, #cacaca); - border: 1px solid transparent; +kb-key { + background-color: #444444; + border-top: 1px solid #666666; border-radius: 3px; - /* Reserving equivalent space to .key:active so - keys don't shift when selected. */ - /* Do not use box shadow until performance improves - * http://code.google.com/p/chromium/issues/detail?id=99045 - box-shadow: 0px 1px 1px #000; - */ - color: #535353; - display: -webkit-box; + color: #ffffff; font-family: sans-serif; font-weight: 100; margin-left: 3px; - position: relative; } -.key > div { - bottom: 0; - left: 0; - margin: auto; - position: absolute; - right: 0; - top: 0; +kb-key.dark { + background-color: #333333; } -.key:active { - background: -webkit-linear-gradient(#d6d6d6, #acacac); - border: 1px solid rgba(125,125,125,0.5); +#upper .left-shift, +#upper .right-shift, +.active { + background-color: #acacac !important; + border-top: 1px solid rgba(125,125,125,0.5); /* Do not use box shadow until performance improves * http://code.google.com/p/chromium/issues/detail?id=99045 box-shadow: 0px 0px 15px #fff; */ } -div.moddown { - background: -webkit-linear-gradient(#d6d6d6, #acacac); - border-color: rgb(48, 74, 155); -} - -.image-key { - background-position: center center; - background-repeat: no-repeat; - background-size: contain; - height: 100%; - width: 100%; -} - -.text-key { - height: 1.2em; -} - - -.shift > div.image-key { - background-image: url('images/shift.svg'); -} - -.moddown.shift > div.image-key { - background-image: url('images/shift-down.svg'); -} - -.hide > div { - background-image: url('images/keyboard.svg'); -} - .at, .com, .comma, .hide, .mic, -.period { - -webkit-box-flex: 1.3; +.period, +.tab { + -webkit-box-flex: 1.3 !important; } .symbol, -.shift { - -webkit-box-flex: 1.4; -} - .return { - -webkit-box-flex: 1.5; + -webkit-box-flex: 1.5 !important; } .backspace { - -webkit-box-flex: 1.6; + -webkit-box-flex: 1.7 !important; } -.left-shift { - -webkit-box-flex: 1.8; +.left-shift, +.left-more { + -webkit-box-flex: 1.4 !important; } -.right-shift { - -webkit-box-flex: 2.0; +.right-shift, +.right-more { + -webkit-box-flex: 1.6 !important; } .space { - -webkit-box-flex: 4.8; + -webkit-box-flex: 4.8 !important; } .bar { - -webkit-box-flex: 0.6; + -webkit-box-flex: 0.6 !important; } -.nodisplay { - display: none; +.backspace, +.tab, +.return, +.left-shift, +.right-shift, +.left-more, +.right-more, +.symbol, +.moddown.shift { + font-size: 80%; +} + +.mic { + background-image: url('images/mic.svg'); +} + +.audio .mic { + background-image: url('images/mic-green.svg'); } |