OLD | NEW |
1 // Copyright 2014 The ChromeOS IME Authors. All Rights Reserved. | 1 // Copyright 2014 The ChromeOS IME Authors. All Rights Reserved. |
2 // limitations under the License. | 2 // limitations under the License. |
3 // See the License for the specific language governing permissions and | 3 // See the License for the specific language governing permissions and |
4 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 4 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
5 // distributed under the License is distributed on an "AS-IS" BASIS, | 5 // distributed under the License is distributed on an "AS-IS" BASIS, |
6 // Unless required by applicable law or agreed to in writing, software | 6 // Unless required by applicable law or agreed to in writing, software |
7 // | 7 // |
8 // http://www.apache.org/licenses/LICENSE-2.0 | 8 // http://www.apache.org/licenses/LICENSE-2.0 |
9 // | 9 // |
10 // You may obtain a copy of the License at | 10 // You may obtain a copy of the License at |
11 // you may not use this file except in compliance with the License. | 11 // you may not use this file except in compliance with the License. |
12 // Licensed under the Apache License, Version 2.0 (the "License"); | 12 // Licensed under the Apache License, Version 2.0 (the "License"); |
13 // | 13 // |
14 goog.provide('i18n.input.chrome.inputview.Controller'); | 14 goog.provide('i18n.input.chrome.inputview.Controller'); |
15 | 15 |
16 goog.require('goog.Disposable'); | 16 goog.require('goog.Disposable'); |
17 goog.require('goog.Timer'); | 17 goog.require('goog.Timer'); |
18 goog.require('goog.array'); | 18 goog.require('goog.array'); |
19 goog.require('goog.async.Delay'); | 19 goog.require('goog.async.Delay'); |
20 goog.require('goog.dom.classlist'); | 20 goog.require('goog.dom.classlist'); |
21 goog.require('goog.events.Event'); | 21 goog.require('goog.events.Event'); |
22 goog.require('goog.events.EventHandler'); | 22 goog.require('goog.events.EventHandler'); |
23 goog.require('goog.events.EventType'); | 23 goog.require('goog.events.EventType'); |
24 goog.require('goog.events.KeyCodes'); | 24 goog.require('goog.events.KeyCodes'); |
| 25 goog.require('goog.fx.easing'); |
25 goog.require('goog.i18n.bidi'); | 26 goog.require('goog.i18n.bidi'); |
| 27 goog.require('goog.math.Coordinate'); |
26 goog.require('goog.object'); | 28 goog.require('goog.object'); |
27 goog.require('i18n.input.chrome.DataSource'); | 29 goog.require('i18n.input.chrome.DataSource'); |
| 30 goog.require('i18n.input.chrome.ElementType'); |
| 31 goog.require('i18n.input.chrome.FeatureName'); |
28 goog.require('i18n.input.chrome.Statistics'); | 32 goog.require('i18n.input.chrome.Statistics'); |
| 33 goog.require('i18n.input.chrome.events.KeyCodes'); |
29 goog.require('i18n.input.chrome.inputview.Adapter'); | 34 goog.require('i18n.input.chrome.inputview.Adapter'); |
30 goog.require('i18n.input.chrome.inputview.CandidatesInfo'); | 35 goog.require('i18n.input.chrome.inputview.CandidatesInfo'); |
31 goog.require('i18n.input.chrome.inputview.ConditionName'); | 36 goog.require('i18n.input.chrome.inputview.ConditionName'); |
32 goog.require('i18n.input.chrome.inputview.Css'); | 37 goog.require('i18n.input.chrome.inputview.Css'); |
33 goog.require('i18n.input.chrome.inputview.FeatureName'); | |
34 goog.require('i18n.input.chrome.inputview.KeyboardContainer'); | 38 goog.require('i18n.input.chrome.inputview.KeyboardContainer'); |
35 goog.require('i18n.input.chrome.inputview.M17nModel'); | 39 goog.require('i18n.input.chrome.inputview.M17nModel'); |
36 goog.require('i18n.input.chrome.inputview.Model'); | 40 goog.require('i18n.input.chrome.inputview.Model'); |
37 goog.require('i18n.input.chrome.inputview.PerfTracker'); | 41 goog.require('i18n.input.chrome.inputview.PerfTracker'); |
38 goog.require('i18n.input.chrome.inputview.ReadyState'); | 42 goog.require('i18n.input.chrome.inputview.ReadyState'); |
39 goog.require('i18n.input.chrome.inputview.Settings'); | 43 goog.require('i18n.input.chrome.inputview.Settings'); |
40 goog.require('i18n.input.chrome.inputview.SizeSpec'); | 44 goog.require('i18n.input.chrome.inputview.SizeSpec'); |
41 goog.require('i18n.input.chrome.inputview.SpecNodeName'); | 45 goog.require('i18n.input.chrome.inputview.SpecNodeName'); |
42 goog.require('i18n.input.chrome.inputview.StateType'); | 46 goog.require('i18n.input.chrome.inputview.StateType'); |
43 goog.require('i18n.input.chrome.inputview.SwipeDirection'); | 47 goog.require('i18n.input.chrome.inputview.SwipeDirection'); |
44 goog.require('i18n.input.chrome.inputview.elements.ElementType'); | |
45 goog.require('i18n.input.chrome.inputview.elements.content.Candidate'); | 48 goog.require('i18n.input.chrome.inputview.elements.content.Candidate'); |
46 goog.require('i18n.input.chrome.inputview.elements.content.CandidateView'); | 49 goog.require('i18n.input.chrome.inputview.elements.content.CandidateView'); |
47 goog.require('i18n.input.chrome.inputview.elements.content.ExpandedCandidateView
'); | 50 goog.require('i18n.input.chrome.inputview.elements.content.ExpandedCandidateView
'); |
48 goog.require('i18n.input.chrome.inputview.elements.content.MenuView'); | 51 goog.require('i18n.input.chrome.inputview.elements.content.MenuView'); |
49 goog.require('i18n.input.chrome.inputview.events.EventType'); | 52 goog.require('i18n.input.chrome.inputview.events.EventType'); |
50 goog.require('i18n.input.chrome.inputview.events.KeyCodes'); | |
51 goog.require('i18n.input.chrome.inputview.handler.PointerHandler'); | 53 goog.require('i18n.input.chrome.inputview.handler.PointerHandler'); |
52 goog.require('i18n.input.chrome.inputview.util'); | 54 goog.require('i18n.input.chrome.inputview.util'); |
53 goog.require('i18n.input.chrome.message.ContextType'); | 55 goog.require('i18n.input.chrome.message.ContextType'); |
54 goog.require('i18n.input.chrome.message.Name'); | 56 goog.require('i18n.input.chrome.message.Name'); |
55 goog.require('i18n.input.chrome.message.Type'); | 57 goog.require('i18n.input.chrome.message.Type'); |
56 goog.require('i18n.input.chrome.sounds.SoundController'); | 58 goog.require('i18n.input.chrome.sounds.SoundController'); |
57 goog.require('i18n.input.lang.InputToolCode'); | 59 goog.require('i18n.input.lang.InputToolCode'); |
58 | 60 |
59 | 61 |
60 | 62 |
61 goog.scope(function() { | 63 goog.scope(function() { |
62 var CandidateType = i18n.input.chrome.inputview.elements.content.Candidate.Type; | 64 var CandidateType = i18n.input.chrome.inputview.elements.content.Candidate.Type; |
63 var CandidateView = i18n.input.chrome.inputview.elements.content.CandidateView; | 65 var CandidateView = i18n.input.chrome.inputview.elements.content.CandidateView; |
64 var ConditionName = i18n.input.chrome.inputview.ConditionName; | 66 var ConditionName = i18n.input.chrome.inputview.ConditionName; |
65 var ContextType = i18n.input.chrome.message.ContextType; | 67 var ContextType = i18n.input.chrome.message.ContextType; |
66 var Css = i18n.input.chrome.inputview.Css; | 68 var Css = i18n.input.chrome.inputview.Css; |
67 var ElementType = i18n.input.chrome.inputview.elements.ElementType; | 69 var ElementType = i18n.input.chrome.ElementType; |
68 var EventType = i18n.input.chrome.inputview.events.EventType; | 70 var EventType = i18n.input.chrome.inputview.events.EventType; |
69 var ExpandedCandidateView = i18n.input.chrome.inputview.elements.content. | 71 var ExpandedCandidateView = i18n.input.chrome.inputview.elements.content. |
70 ExpandedCandidateView; | 72 ExpandedCandidateView; |
71 var FeatureName = i18n.input.chrome.inputview.FeatureName; | 73 var FeatureName = i18n.input.chrome.FeatureName; |
72 var InputToolCode = i18n.input.lang.InputToolCode; | 74 var InputToolCode = i18n.input.lang.InputToolCode; |
73 var KeyCodes = i18n.input.chrome.inputview.events.KeyCodes; | 75 var KeyCodes = i18n.input.chrome.events.KeyCodes; |
74 var MenuView = i18n.input.chrome.inputview.elements.content.MenuView; | 76 var MenuView = i18n.input.chrome.inputview.elements.content.MenuView; |
75 var Name = i18n.input.chrome.message.Name; | 77 var Name = i18n.input.chrome.message.Name; |
76 var PerfTracker = i18n.input.chrome.inputview.PerfTracker; | 78 var PerfTracker = i18n.input.chrome.inputview.PerfTracker; |
77 var SizeSpec = i18n.input.chrome.inputview.SizeSpec; | 79 var SizeSpec = i18n.input.chrome.inputview.SizeSpec; |
78 var SpecNodeName = i18n.input.chrome.inputview.SpecNodeName; | 80 var SpecNodeName = i18n.input.chrome.inputview.SpecNodeName; |
79 var StateType = i18n.input.chrome.inputview.StateType; | 81 var StateType = i18n.input.chrome.inputview.StateType; |
80 var SoundController = i18n.input.chrome.sounds.SoundController; | 82 var SoundController = i18n.input.chrome.sounds.SoundController; |
81 var Type = i18n.input.chrome.message.Type; | 83 var Type = i18n.input.chrome.message.Type; |
82 var events = i18n.input.chrome.inputview.events; | 84 var events = i18n.input.chrome.inputview.events; |
83 var util = i18n.input.chrome.inputview.util; | 85 var util = i18n.input.chrome.inputview.util; |
84 | 86 |
85 | 87 |
| 88 /** |
| 89 * Time in milliseconds after which backspace will start autorepeating. |
| 90 * @const {number} |
| 91 */ |
| 92 var BACKSPACE_REPEAT_START_TIME_MS = 300; |
| 93 |
| 94 |
| 95 /** |
| 96 * Minimum time, in milliseconds, after which backspace can repeat. This |
| 97 * prevents deleting entire pages in a go. |
| 98 * @const {number} |
| 99 */ |
| 100 var MINIMUM_BACKSPACE_REPEAT_TIME_MS = 25; |
| 101 |
| 102 |
| 103 /** |
| 104 * Maximum time, in milliseconds, after which the backspace can repeat. |
| 105 * @const {number} |
| 106 */ |
| 107 var MAXIMUM_BACKSPACE_REPEAT_TIME_MS = 75; |
| 108 |
| 109 |
| 110 /** |
| 111 * The limit for backspace repeat for speeding up. |
| 112 * The backspace repeat beyond this limit will have the maximum speed. |
| 113 * @const {number} |
| 114 */ |
| 115 var BACKSPACE_REPEAT_LIMIT = 255; |
| 116 |
| 117 |
| 118 /** |
| 119 * The time, in milliseconds, that the gesture preview window lingers before |
| 120 * being dismissed. |
| 121 * |
| 122 * @const {number} |
| 123 */ |
| 124 var GESTURE_PREVIEW_LINGER_TIME_MS = 250; |
| 125 |
| 126 |
| 127 /** |
| 128 * The maximum distance from the top of the keyboard that a gesture can move |
| 129 * before it cancels the gesture typing gesture. |
| 130 * |
| 131 * @const {number} |
| 132 */ |
| 133 var MAXIMUM_DISTANCE_FROM_TOP_FOR_GESTURES = 40; |
| 134 |
| 135 |
| 136 /** |
| 137 * The hotrod customized layout code. |
| 138 * |
| 139 * @const {string} |
| 140 */ |
| 141 var HOTROD_DEFAULT_KEYSET = 'hotrod'; |
| 142 |
| 143 |
86 | 144 |
87 /** | 145 /** |
88 * The controller of the input view keyboard. | 146 * The controller of the input view keyboard. |
89 * | 147 * |
90 * @param {string} keyset The keyboard keyset. | 148 * @param {string} keyset The keyboard keyset. |
91 * @param {string} languageCode The language code for this keyboard. | 149 * @param {string} languageCode The language code for this keyboard. |
92 * @param {string} passwordLayout The layout for password box. | 150 * @param {string} passwordLayout The layout for password box. |
93 * @param {string} name The input tool name. | 151 * @param {string} name The input tool name. |
94 * @constructor | 152 * @constructor |
95 * @extends {goog.Disposable} | 153 * @extends {goog.Disposable} |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 /** @private {!i18n.input.chrome.inputview.ReadyState} */ | 235 /** @private {!i18n.input.chrome.inputview.ReadyState} */ |
178 this.readyState_ = new i18n.input.chrome.inputview.ReadyState(); | 236 this.readyState_ = new i18n.input.chrome.inputview.ReadyState(); |
179 | 237 |
180 /** @private {!i18n.input.chrome.inputview.Adapter} */ | 238 /** @private {!i18n.input.chrome.inputview.Adapter} */ |
181 this.adapter_ = new i18n.input.chrome.inputview.Adapter(this.readyState_); | 239 this.adapter_ = new i18n.input.chrome.inputview.Adapter(this.readyState_); |
182 | 240 |
183 /** @private {!SoundController} */ | 241 /** @private {!SoundController} */ |
184 this.soundController_ = new SoundController(false); | 242 this.soundController_ = new SoundController(false); |
185 | 243 |
186 /** | 244 /** |
187 * Whether or not to commit the next gesture result. | 245 * Whether or not the candidates were last set by gesture typing. |
188 * | 246 * |
189 * @private {boolean} | 247 * @private {boolean} |
190 */ | 248 */ |
191 this.commitNextGestureResult_ = false; | 249 this.candidatesSetByGestureTyping_ = false; |
192 | 250 |
193 /** @private {!i18n.input.chrome.inputview.KeyboardContainer} */ | 251 /** @private {!i18n.input.chrome.inputview.KeyboardContainer} */ |
194 this.container_ = new i18n.input.chrome.inputview.KeyboardContainer( | 252 this.container_ = new i18n.input.chrome.inputview.KeyboardContainer( |
195 this.adapter_, this.soundController_); | 253 this.adapter_, this.soundController_); |
196 | 254 |
197 /** | 255 /** |
198 * The context type and keyset mapping group by input method id. | 256 * The context type and keyset mapping group by input method id. |
199 * key: input method id. | 257 * key: input method id. |
200 * value: Object | 258 * value: Object |
201 * key: context type string. | 259 * key: context type string. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 /** | 307 /** |
250 * The suggestions. | 308 * The suggestions. |
251 * Note: sets a default empty result to avoid null check. | 309 * Note: sets a default empty result to avoid null check. |
252 * | 310 * |
253 * @private {!i18n.input.chrome.inputview.CandidatesInfo} | 311 * @private {!i18n.input.chrome.inputview.CandidatesInfo} |
254 */ | 312 */ |
255 this.candidatesInfo_ = i18n.input.chrome.inputview.CandidatesInfo.getEmpty(); | 313 this.candidatesInfo_ = i18n.input.chrome.inputview.CandidatesInfo.getEmpty(); |
256 | 314 |
257 this.registerEventHandler_(); | 315 this.registerEventHandler_(); |
258 }; | 316 }; |
259 goog.inherits(i18n.input.chrome.inputview.Controller, | 317 goog.inherits(i18n.input.chrome.inputview.Controller, goog.Disposable); |
260 goog.Disposable); | |
261 var Controller = i18n.input.chrome.inputview.Controller; | 318 var Controller = i18n.input.chrome.inputview.Controller; |
| 319 var Statistics = i18n.input.chrome.Statistics; |
| 320 |
| 321 /** |
| 322 * @define {boolean} Flag to disable delayed loading of non active keyset. It |
| 323 * should only be used in testing. |
| 324 */ |
| 325 Controller.DISABLE_DELAY_LOADING_FOR_TEST = false; |
262 | 326 |
263 | 327 |
264 /** | 328 /** |
265 * @define {boolean} Flag to disable handwriting. | 329 * @define {boolean} Flag to disable handwriting. |
266 */ | 330 */ |
267 Controller.DISABLE_HWT = false; | 331 Controller.DISABLE_HWT = false; |
268 | 332 |
269 | 333 |
270 /** | 334 /** |
271 * A flag to indicate whether the shift is for auto capital. | 335 * A flag to indicate whether the shift is for auto capital. |
(...skipping 21 matching lines...) Expand all Loading... |
293 /** | 357 /** |
294 * The emoji view code, use the code can switch to emoji. | 358 * The emoji view code, use the code can switch to emoji. |
295 * | 359 * |
296 * @const {string} | 360 * @const {string} |
297 * @private | 361 * @private |
298 */ | 362 */ |
299 Controller.EMOJI_VIEW_CODE_ = 'emoji'; | 363 Controller.EMOJI_VIEW_CODE_ = 'emoji'; |
300 | 364 |
301 | 365 |
302 /** | 366 /** |
303 * The limitation for backspace repeat time to avoid unexpected | |
304 * problem that backspace is held all the time. | |
305 * | |
306 * @private {number} | |
307 */ | |
308 Controller.BACKSPACE_REPEAT_LIMIT_ = 255; | |
309 | |
310 | |
311 /** | |
312 * The repeated times of the backspace. | 367 * The repeated times of the backspace. |
313 * | 368 * |
314 * @private {number} | 369 * @private {number} |
315 */ | 370 */ |
316 Controller.prototype.backspaceRepeated_ = 0; | 371 Controller.prototype.backspaceRepeated_ = 0; |
317 | 372 |
318 | 373 |
319 /** | 374 /** |
320 * The handwriting input tool code suffix. | 375 * The handwriting input tool code suffix. |
321 * | 376 * |
322 * @const {string} | 377 * @const {string} |
323 * @private | 378 * @private |
324 */ | 379 */ |
325 Controller.HANDWRITING_CODE_SUFFIX_ = '-t-i0-handwrit'; | 380 Controller.HANDWRITING_CODE_SUFFIX_ = '-t-i0-handwrit'; |
326 | 381 |
327 | 382 |
328 /** | 383 /** |
329 * The US English compact layout prefix. | 384 * The US English compact layout qwerty code. |
330 * | 385 * |
331 * @const {string} | 386 * @const {string} |
332 * @private | 387 * @private |
333 */ | 388 */ |
334 Controller.US_COMPACT_PREFIX_ = 'us.compact'; | 389 Controller.US_COMPACT_QWERTY_CODE_ = 'us.compact.qwerty'; |
335 | 390 |
336 | 391 |
337 /** | 392 /** |
338 * Time threshold between samples sent to the back end. | 393 * Time threshold between samples sent to the back end. |
339 * | 394 * |
340 * @const {number} | 395 * @const {number} |
341 */ | 396 */ |
342 Controller.SUBSAMPLING_TIME_THRESHOLD = 100; | 397 Controller.SUBSAMPLING_TIME_THRESHOLD = 100; |
343 | 398 |
344 | 399 |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
610 } | 665 } |
611 if (goog.isDef(e.msg['doubleSpacePeriod'])) { | 666 if (goog.isDef(e.msg['doubleSpacePeriod'])) { |
612 settings.doubleSpacePeriod = e.msg['doubleSpacePeriod']; | 667 settings.doubleSpacePeriod = e.msg['doubleSpacePeriod']; |
613 } | 668 } |
614 if (goog.isDef(e.msg['soundOnKeypress'])) { | 669 if (goog.isDef(e.msg['soundOnKeypress'])) { |
615 settings.soundOnKeypress = e.msg['soundOnKeypress']; | 670 settings.soundOnKeypress = e.msg['soundOnKeypress']; |
616 this.soundController_.setEnabled(settings.soundOnKeypress); | 671 this.soundController_.setEnabled(settings.soundOnKeypress); |
617 } | 672 } |
618 if (goog.isDef(e.msg['gestureEditing'])) { | 673 if (goog.isDef(e.msg['gestureEditing'])) { |
619 settings.gestureEditing = e.msg['gestureEditing']; | 674 settings.gestureEditing = e.msg['gestureEditing']; |
620 var enabled = settings.gestureEditing && !this.adapter_.isA11yMode; | 675 var enabled = settings.gestureEditing && !this.adapter_.isA11yMode && |
| 676 !this.adapter_.isHotrod && |
| 677 !this.adapter_.isFloatingVirtualKeyboardEnabled(); |
621 this.container_.swipeView.enabled = enabled; | 678 this.container_.swipeView.enabled = enabled; |
622 this.container_.selectView.setSettingsEnabled(enabled); | 679 this.container_.selectView.setSettingsEnabled(enabled); |
623 } | 680 } |
624 if (goog.isDef(e.msg['gestureTyping'])) { | 681 if (goog.isDef(e.msg['gestureTyping'])) { |
625 settings.gestureTyping = e.msg['gestureTyping']; | 682 settings.gestureTyping = e.msg['gestureTyping']; |
626 } else { | 683 } else { |
627 settings.gestureTyping = false; | 684 settings.gestureTyping = false; |
628 } | 685 } |
629 this.perfTracker_.tick(PerfTracker.TickName.BACKGROUND_SETTINGS_FETCHED); | 686 this.perfTracker_.tick(PerfTracker.TickName.BACKGROUND_SETTINGS_FETCHED); |
630 this.model_.stateManager.contextType = this.adapter_.contextType; | 687 this.model_.stateManager.contextType = this.adapter_.contextType; |
(...skipping 23 matching lines...) Expand all Loading... |
654 | 711 |
655 this.isSettingReady = true; | 712 this.isSettingReady = true; |
656 // Don't render container twice. | 713 // Don't render container twice. |
657 if (!this.container_.isInDocument()) { | 714 if (!this.container_.isInDocument()) { |
658 this.container_.render(); | 715 this.container_.render(); |
659 } | 716 } |
660 var keysetMap = this.contextTypeToKeysetMap_[this.currentInputMethod_]; | 717 var keysetMap = this.contextTypeToKeysetMap_[this.currentInputMethod_]; |
661 var newKeyset = ''; | 718 var newKeyset = ''; |
662 if (this.adapter_.isA11yMode) { | 719 if (this.adapter_.isA11yMode) { |
663 newKeyset = util.getConfigName(keysetMap[ContextType.DEFAULT]); | 720 newKeyset = util.getConfigName(keysetMap[ContextType.DEFAULT]); |
| 721 } else if (this.adapter_.isHotrod) { |
| 722 newKeyset = HOTROD_DEFAULT_KEYSET; |
664 } else { | 723 } else { |
665 newKeyset = /** @type {string} */ (this.model_.settings. | 724 newKeyset = /** @type {string} */ (this.model_.settings. |
666 getPreference(util.getConfigName(keysetMap[ContextType.DEFAULT]))); | 725 getPreference(util.getConfigName(keysetMap[ContextType.DEFAULT]))); |
667 } | 726 } |
668 if (!this.adapter_.features.isEnabled(FeatureName.EXPERIMENTAL) && | 727 |
669 keysetMap[ContextType.DEFAULT] == | |
670 'zhuyin.compact.qwerty') { | |
671 newKeyset = 'zhuyin'; | |
672 } | |
673 if (newKeyset) { | 728 if (newKeyset) { |
674 this.setDefaultKeyset_(newKeyset); | 729 this.setDefaultKeyset_(newKeyset); |
675 } | 730 } |
676 this.container_.selectView.setSettingsEnabled( | 731 this.container_.selectView.setSettingsEnabled( |
677 this.model_.settings.gestureEditing && !this.adapter_.isA11yMode); | 732 this.model_.settings.gestureEditing && !this.adapter_.isA11yMode && |
| 733 !this.adapter_.isHotrod); |
678 // Loads resources in case the default keyset is changed. | 734 // Loads resources in case the default keyset is changed. |
679 this.loadAllResources_(); | 735 this.loadAllResources_(); |
680 this.maybeCreateViews_(); | 736 this.maybeCreateViews_(); |
681 }; | 737 }; |
682 | 738 |
683 | 739 |
684 /** | 740 /** |
685 * Returns whether or not the gesture typing feature is enabled. | 741 * Returns whether or not the gesture typing feature is enabled. |
686 * | 742 * |
687 * @return {boolean} | 743 * @return {boolean} |
688 * @private | 744 * @private |
689 */ | 745 */ |
690 Controller.prototype.gestureTypingEnabled_ = function() { | 746 Controller.prototype.gestureTypingEnabled_ = function() { |
691 return this.isKeysetUSCompact_ && this.model_.settings.gestureTyping && | 747 return this.isKeysetUSCompact_ && this.model_.settings.gestureTyping && |
692 !this.adapter_.isA11yMode && !this.adapter_.isChromeVoxOn; | 748 !this.adapter_.isA11yMode && !this.adapter_.isHotrod && |
| 749 !this.adapter_.isChromeVoxOn && |
| 750 !this.adapter_.isPasswordBox() && |
| 751 !this.adapter_.isFloatingVirtualKeyboardEnabled() && |
| 752 !this.container_.altDataView.isVisible() && |
| 753 !this.container_.menuView.isVisible() && |
| 754 !this.container_.voiceView.isVisible(); |
693 }; | 755 }; |
694 | 756 |
695 | 757 |
696 /** | 758 /** |
697 * Returns the time threshold for subsampling, in ms. | 759 * Returns the time threshold for subsampling, in ms. |
698 * | 760 * |
699 * @return {number} | 761 * @return {number} |
700 * @private | 762 * @private |
701 */ | 763 */ |
702 Controller.prototype.subsamplingThreshold_ = function() { | 764 Controller.prototype.subsamplingThreshold_ = function() { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 | 803 |
742 | 804 |
743 /** | 805 /** |
744 * Gets the key content. | 806 * Gets the key content. |
745 * | 807 * |
746 * @param {!i18n.input.chrome.inputview.elements.content.SoftKey} key . | 808 * @param {!i18n.input.chrome.inputview.elements.content.SoftKey} key . |
747 * @return {string} . | 809 * @return {string} . |
748 * @private | 810 * @private |
749 */ | 811 */ |
750 Controller.prototype.getKeyContent_ = function(key) { | 812 Controller.prototype.getKeyContent_ = function(key) { |
751 if (key.type == i18n.input.chrome.inputview.elements.ElementType. | 813 if (key.type == i18n.input.chrome.ElementType. |
752 CHARACTER_KEY) { | 814 CHARACTER_KEY) { |
753 key = /** @type {!i18n.input.chrome.inputview.elements.content. | 815 key = /** @type {!i18n.input.chrome.inputview.elements.content. |
754 CharacterKey} */ (key); | 816 CharacterKey} */ (key); |
755 return key.getActiveCharacter(); | 817 return key.getActiveCharacter(); |
756 } | 818 } |
757 if (key.type == i18n.input.chrome.inputview.elements.ElementType. | 819 if (key.type == i18n.input.chrome.ElementType. |
758 COMPACT_KEY) { | 820 COMPACT_KEY) { |
759 key = /** @type {!i18n.input.chrome.inputview.elements.content. | 821 key = /** @type {!i18n.input.chrome.inputview.elements.content. |
760 FunctionalKey} */ (key); | 822 FunctionalKey} */ (key); |
761 return key.text; | 823 return key.text; |
762 } | 824 } |
763 return ''; | 825 return ''; |
764 }; | 826 }; |
765 | 827 |
766 | 828 |
767 /** | 829 /** |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
826 if (!opt_force && currentTime - this.lastPointTime_ < | 888 if (!opt_force && currentTime - this.lastPointTime_ < |
827 this.subsamplingThreshold_()) { | 889 this.subsamplingThreshold_()) { |
828 return; | 890 return; |
829 } else { | 891 } else { |
830 this.lastPointTime_ = currentTime; | 892 this.lastPointTime_ = currentTime; |
831 } | 893 } |
832 var lastStroke = this.container_.gestureCanvasView.getLastStroke(); | 894 var lastStroke = this.container_.gestureCanvasView.getLastStroke(); |
833 if (lastStroke) { | 895 if (lastStroke) { |
834 // This call will set up the necessary callbacks the decoder will use to | 896 // This call will set up the necessary callbacks the decoder will use to |
835 // communicate back to this class. | 897 // communicate back to this class. |
836 this.adapter_.sendGestureEvent(lastStroke.points); | 898 this.adapter_.sendGestureEvent(lastStroke.getPoints()); |
837 } | 899 } |
838 }; | 900 }; |
839 | 901 |
840 | 902 |
841 /** | 903 /** |
842 * Handles the drag events. Generally, this will forward the event details to | 904 * Handles the drag events. Generally, this will forward the event details to |
843 * the components that handle drawing, decoding, etc. | 905 * the components that handle drawing, decoding, etc. |
844 * | 906 * |
845 * @param {!i18n.input.chrome.inputview.events.DragEvent} e . | 907 * @param {!i18n.input.chrome.inputview.events.DragEvent} e . |
846 * @private | 908 * @private |
847 */ | 909 */ |
848 Controller.prototype.onDragEvent_ = function(e) { | 910 Controller.prototype.onDragEvent_ = function(e) { |
849 if (this.gestureTypingEnabled_() && e.type == EventType.DRAG && | 911 if (this.gestureTypingEnabled_() && e.type == EventType.DRAG && |
850 !this.container_.swipeView.isVisible()) { | 912 !this.container_.swipeView.isVisible()) { |
| 913 // Conveniently, the DragEvent has coordinates relative to the gesture |
| 914 // canvas view, so we can test it's y coordinate in order to determine if |
| 915 // we're off the canvas. |
| 916 if (e.y + MAXIMUM_DISTANCE_FROM_TOP_FOR_GESTURES < 0) { |
| 917 this.container_.gestureCanvasView.clear(); |
| 918 this.container_.gesturePreviewWindow.hide(); |
| 919 this.clearCandidates_(); |
| 920 return; |
| 921 } |
851 this.container_.gestureCanvasView.addPoint(e); | 922 this.container_.gestureCanvasView.addPoint(e); |
852 if (e.view && this.container_.gestureCanvasView.isGesturing) { | 923 if (e.view && this.container_.gestureCanvasView.isGesturing) { |
853 // Ensure the last touched key is not highlighted. | 924 // Ensure the last touched key is not highlighted. |
854 e.view.setHighlighted(false); | 925 if (e.view.type != ElementType.MODIFIER_KEY) { |
| 926 e.view.setHighlighted(false); |
| 927 } |
855 this.maybeSendLastStroke_(); | 928 this.maybeSendLastStroke_(); |
| 929 // Reposition the gesture preview window to follow the user's touch point. |
| 930 if (this.container_.gesturePreviewWindow && |
| 931 this.container_.gestureCanvasView.isActiveIdentifier( |
| 932 e.identifier)) { |
| 933 this.container_.gesturePreviewWindow.reposition( |
| 934 new goog.math.Coordinate(e.x, e.y)); |
| 935 } |
856 } | 936 } |
857 return; | |
858 } | 937 } |
859 }; | 938 }; |
860 | 939 |
861 | 940 |
862 /** | 941 /** |
863 * Handles the swipe action. | 942 * Handles the swipe action. |
864 * | 943 * |
865 * @param {!i18n.input.chrome.inputview.elements.Element} view The view, for | 944 * @param {!i18n.input.chrome.inputview.elements.Element} view The view, for |
866 * swipe event, the view would be the soft key which starts the swipe. | 945 * swipe event, the view would be the soft key which starts the swipe. |
867 * @param {!i18n.input.chrome.inputview.events.SwipeEvent} e The swipe event. | 946 * @param {!i18n.input.chrome.inputview.events.SwipeEvent} e The swipe event. |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
942 this.currentKeyset_; | 1021 this.currentKeyset_; |
943 // TODO: remember handwriting keyset. | 1022 // TODO: remember handwriting keyset. |
944 this.switchToKeyset(Controller.HANDWRITING_VIEW_CODE_); | 1023 this.switchToKeyset(Controller.HANDWRITING_VIEW_CODE_); |
945 break; | 1024 break; |
946 | 1025 |
947 case CommandEnum.OPEN_SETTING: | 1026 case CommandEnum.OPEN_SETTING: |
948 if (window.inputview) { | 1027 if (window.inputview) { |
949 inputview.openSettings(); | 1028 inputview.openSettings(); |
950 } | 1029 } |
951 break; | 1030 break; |
952 | |
953 case CommandEnum.FLOATING: | |
954 if (inputview.setMode) { | |
955 inputview.setMode('FLOATING'); | |
956 this.adapter_.isFloating = true; | |
957 this.container_.candidateView.setFloatingVKButtonsVisible(true); | |
958 this.resize(); | |
959 setTimeout(function() { | |
960 var x = Math.floor((screen.width - window.innerWidth) / 2); | |
961 window.moveTo(x, window.screenY); | |
962 }, 0); | |
963 } | |
964 break; | |
965 | |
966 case CommandEnum.DOCKING: | |
967 if (inputview.setMode) { | |
968 inputview.setMode('FULL_WIDTH'); | |
969 this.adapter_.isFloating = false; | |
970 this.container_.candidateView.setFloatingVKButtonsVisible(false); | |
971 } | |
972 break; | |
973 | |
974 } | 1031 } |
975 }; | 1032 }; |
976 | 1033 |
977 | 1034 |
| 1035 /** |
| 1036 * Returns the gesture typing event type for a given candidate ID. |
| 1037 * |
| 1038 * @param {number} candidateID The candidate ID to convert. |
| 1039 * @return {?i18n.input.chrome.Statistics.GestureTypingEvent} The gesture |
| 1040 * typing event type for the given candidate. Null if the candidate was not |
| 1041 * found. |
| 1042 * @private |
| 1043 */ |
| 1044 Controller.prototype.getGestureEventTypeForCandidateID_ = |
| 1045 function(candidateID) { |
| 1046 if (candidateID == 0) { |
| 1047 return Statistics.GestureTypingEvent.REPLACED_0; |
| 1048 } else if (candidateID == 1) { |
| 1049 return Statistics.GestureTypingEvent.REPLACED_1; |
| 1050 } else if (candidateID >= 2) { |
| 1051 return Statistics.GestureTypingEvent.REPLACED_2; |
| 1052 } |
| 1053 return null; |
| 1054 }; |
| 1055 |
| 1056 |
978 /** | 1057 /** |
979 * Handles the pointer action. | 1058 * Handles the pointer action. |
980 * | 1059 * |
981 * @param {!i18n.input.chrome.inputview.elements.Element} view The view. | 1060 * @param {!i18n.input.chrome.inputview.elements.Element} view The view. |
982 * @param {!i18n.input.chrome.inputview.events.PointerEvent} e . | 1061 * @param {!i18n.input.chrome.inputview.events.PointerEvent} e . |
983 * @private | 1062 * @private |
984 */ | 1063 */ |
985 Controller.prototype.handlePointerAction_ = function(view, e) { | 1064 Controller.prototype.handlePointerAction_ = function(view, e) { |
986 if (this.gestureTypingEnabled_() && !this.container_.swipeView.isVisible()) { | 1065 if (this.gestureTypingEnabled_() && !this.container_.swipeView.isVisible()) { |
987 if (e.type == EventType.POINTER_DOWN) { | 1066 if (e.type == EventType.POINTER_DOWN) { |
| 1067 // Do some clean up before starting a new stroke. |
| 1068 this.container_.gestureCanvasView.removeEmptyStrokes(); |
988 this.container_.gestureCanvasView.startStroke(e); | 1069 this.container_.gestureCanvasView.startStroke(e); |
989 view.setHighlighted(false); | 1070 if (view.type != ElementType.MODIFIER_KEY) { |
| 1071 view.setHighlighted(false); |
| 1072 } |
990 } | 1073 } |
991 | 1074 |
992 // Determine if the gestureCanvasView was handling a gesture before calling | 1075 // Determine if the gestureCanvasView was handling a gesture before calling |
993 // endStroke, as it ends the current gesture. | 1076 // endStroke, as it ends the current gesture. |
994 var wasGesturing = this.container_.gestureCanvasView.isGesturing; | 1077 var wasGesturing = this.container_.gestureCanvasView.isGesturing; |
995 if (e.type == EventType.POINTER_UP && wasGesturing) { | 1078 if (e.type == EventType.POINTER_UP && wasGesturing) { |
996 this.container_.gestureCanvasView.endStroke(e); | 1079 this.container_.gestureCanvasView.endStroke(e); |
997 this.maybeSendLastStroke_(true); | 1080 this.maybeSendLastStroke_(true); |
998 this.commitNextGestureResult_ = true; | |
999 } | 1081 } |
1000 | 1082 |
1001 // Do not trigger other activities when gesturing. | 1083 // Do not trigger other activities when gesturing. |
1002 if (wasGesturing) { | 1084 if (wasGesturing) { |
1003 if (e.type == EventType.POINTER_OVER) { | 1085 if (view.type != ElementType.MODIFIER_KEY && |
| 1086 (e.type == EventType.POINTER_OVER || |
| 1087 e.type == EventType.POINTER_OUT)) { |
1004 view.setHighlighted(false); | 1088 view.setHighlighted(false); |
1005 } | 1089 } |
1006 return; | 1090 return; |
1007 } | 1091 } |
1008 } | 1092 } |
1009 | 1093 |
1010 // Listen for DOUBLE_CLICK as well to capture secondary taps on the spacebar. | 1094 // Listen for DOUBLE_CLICK as well to capture secondary taps on the spacebar. |
1011 if (e.type == EventType.POINTER_UP || e.type == EventType.DOUBLE_CLICK) { | 1095 if (e.type == EventType.POINTER_UP || e.type == EventType.DOUBLE_CLICK) { |
1012 this.recordStatsForClosing_( | 1096 this.recordStatsForClosing_( |
1013 'InputMethod.VirtualKeyboard.TapCount', 1, 4095, 4096); | 1097 'InputMethod.VirtualKeyboard.TapCount', 1, 4095, 4096); |
1014 } | 1098 } |
1015 | 1099 |
1016 if (e.type == EventType.SWIPE) { | 1100 if (e.type == EventType.SWIPE) { |
1017 e = /** @type {!i18n.input.chrome.inputview.events.SwipeEvent} */ (e); | 1101 e = /** @type {!i18n.input.chrome.inputview.events.SwipeEvent} */ (e); |
1018 this.handleSwipeAction_(view, e); | 1102 this.handleSwipeAction_(view, e); |
1019 } | 1103 } |
1020 switch (view.type) { | 1104 switch (view.type) { |
1021 case ElementType.KEYBOARD_CONTAINER_VIEW: | 1105 case ElementType.HOTROD_SWITCHER_KEY: |
1022 if (e.type == EventType.POINTER_DOWN) { | |
1023 var tabbableKeysets = [ | |
1024 Controller.HANDWRITING_VIEW_CODE_, | |
1025 Controller.EMOJI_VIEW_CODE_]; | |
1026 if (goog.array.contains(tabbableKeysets, this.currentKeyset_)) { | |
1027 this.resetAll(); | |
1028 this.switchToKeyset(this.container_.currentKeysetView.fromKeyset); | |
1029 } | |
1030 } | |
1031 return; | |
1032 case ElementType.BACK_BUTTON: | 1106 case ElementType.BACK_BUTTON: |
1033 case ElementType.BACK_TO_KEYBOARD: | 1107 case ElementType.BACK_TO_KEYBOARD: |
| 1108 if (view.type == ElementType.HOTROD_SWITCHER_KEY && |
| 1109 !this.adapter_.isHotrod) { |
| 1110 return; |
| 1111 } |
1034 if (e.type == EventType.POINTER_OUT || e.type == EventType.POINTER_UP) { | 1112 if (e.type == EventType.POINTER_OUT || e.type == EventType.POINTER_UP) { |
1035 view.setHighlighted(false); | 1113 view.setHighlighted(false); |
1036 } else if (e.type == EventType.POINTER_DOWN || | 1114 } else if (e.type == EventType.POINTER_DOWN || |
1037 e.type == EventType.POINTER_OVER) { | 1115 e.type == EventType.POINTER_OVER) { |
1038 view.setHighlighted(true); | 1116 view.setHighlighted(true); |
1039 } | 1117 } |
1040 if (e.type == EventType.POINTER_UP) { | 1118 if (e.type == EventType.POINTER_UP) { |
1041 this.switchToKeyset(this.container_.currentKeysetView.fromKeyset); | 1119 var backToKeyset = this.container_.currentKeysetView.fromKeyset; |
| 1120 if (view.type == ElementType.HOTROD_SWITCHER_KEY && |
| 1121 this.adapter_.isHotrod) { |
| 1122 backToKeyset = Controller.US_COMPACT_QWERTY_CODE_; |
| 1123 } |
| 1124 this.switchToKeyset(backToKeyset); |
1042 this.clearCandidates_(); | 1125 this.clearCandidates_(); |
1043 this.soundController_.onKeyUp(view.type); | 1126 this.soundController_.onKeyUp(view.type); |
1044 } | 1127 } |
1045 return; | 1128 return; |
1046 case ElementType.EXPAND_CANDIDATES: | 1129 case ElementType.EXPAND_CANDIDATES: |
1047 if (e.type == EventType.POINTER_UP) { | 1130 if (e.type == EventType.POINTER_UP) { |
1048 this.showCandidates_(this.candidatesInfo_.source, | 1131 this.showCandidates_(this.candidatesInfo_.source, |
1049 this.candidatesInfo_.candidates, | 1132 this.candidatesInfo_.candidates, |
1050 Controller.CandidatesOperation.EXPAND); | 1133 Controller.CandidatesOperation.EXPAND); |
1051 this.soundController_.onKeyUp(view.type); | 1134 this.soundController_.onKeyUp(view.type); |
1052 } | 1135 } |
1053 return; | 1136 return; |
1054 case ElementType.SHRINK_CANDIDATES: | 1137 case ElementType.SHRINK_CANDIDATES: |
1055 if (e.type == EventType.POINTER_UP) { | 1138 if (e.type == EventType.POINTER_UP) { |
1056 this.showCandidates_(this.candidatesInfo_.source, | 1139 this.showCandidates_(this.candidatesInfo_.source, |
1057 this.candidatesInfo_.candidates, | 1140 this.candidatesInfo_.candidates, |
1058 Controller.CandidatesOperation.SHRINK); | 1141 Controller.CandidatesOperation.SHRINK); |
1059 this.soundController_.onKeyUp(view.type); | 1142 this.soundController_.onKeyUp(view.type); |
1060 } | 1143 } |
1061 return; | 1144 return; |
1062 case ElementType.CANDIDATE: | 1145 case ElementType.CANDIDATE: |
1063 view = /** @type {!i18n.input.chrome.inputview.elements.content. | 1146 view = /** @type {!i18n.input.chrome.inputview.elements.content. |
1064 Candidate} */ (view); | 1147 Candidate} */ (view); |
1065 if (view.candidateType == CandidateType.TOOLTIP) | 1148 if (view.candidateType == CandidateType.TOOLTIP) |
1066 return; | 1149 return; |
1067 if (e.type == EventType.POINTER_UP) { | 1150 if (e.type == EventType.POINTER_UP) { |
1068 if (view.candidateType == CandidateType.CANDIDATE) { | 1151 if (view.candidateType == CandidateType.CANDIDATE) { |
1069 this.adapter_.selectCandidate(view.candidate); | 1152 this.adapter_.selectCandidate(view.candidate); |
| 1153 if (this.candidatesSetByGestureTyping_) { |
| 1154 var type = this.getGestureEventTypeForCandidateID_( |
| 1155 view.candidate[Name.CANDIDATE_ID]); |
| 1156 if (type) { |
| 1157 this.statistics_.recordEnum( |
| 1158 Statistics.GESTURE_TYPING_METRIC_NAME, |
| 1159 type, |
| 1160 Statistics.GestureTypingEvent.MAX); |
| 1161 } |
| 1162 } |
1070 } else if (view.candidateType == CandidateType.NUMBER) { | 1163 } else if (view.candidateType == CandidateType.NUMBER) { |
1071 this.adapter_.sendKeyDownAndUpEvent( | 1164 this.adapter_.sendKeyDownAndUpEvent( |
1072 view.candidate[Name.CANDIDATE], ''); | 1165 view.candidate[Name.CANDIDATE], ''); |
1073 } | 1166 } |
1074 this.container_.cleanStroke(); | 1167 this.container_.cleanStroke(); |
1075 this.soundController_.onKeyUp(ElementType.CANDIDATE); | 1168 this.soundController_.onKeyUp(ElementType.CANDIDATE); |
1076 } | 1169 } |
1077 if (e.type == EventType.POINTER_OUT || e.type == EventType.POINTER_UP) { | 1170 if (e.type == EventType.POINTER_OUT || e.type == EventType.POINTER_UP) { |
1078 view.setHighlighted(false); | 1171 view.setHighlighted(false); |
1079 } else if (e.type == EventType.POINTER_DOWN || | 1172 } else if (e.type == EventType.POINTER_DOWN || |
(...skipping 12 matching lines...) Expand all Loading... |
1092 view.triggeredBy.keyCode, | 1185 view.triggeredBy.keyCode, |
1093 {'sources': [ch.toLowerCase()], 'possibilities': [1]}); | 1186 {'sources': [ch.toLowerCase()], 'possibilities': [1]}); |
1094 } | 1187 } |
1095 view.hide(); | 1188 view.hide(); |
1096 this.clearUnstickyState_(); | 1189 this.clearUnstickyState_(); |
1097 this.soundController_.onKeyUp(view.type); | 1190 this.soundController_.onKeyUp(view.type); |
1098 } | 1191 } |
1099 return; | 1192 return; |
1100 | 1193 |
1101 case ElementType.MENU_ITEM: | 1194 case ElementType.MENU_ITEM: |
| 1195 if (this.adapter_.isHotrod) { |
| 1196 // Disable menu items in hotrod. Fix this if hotrod needs i18n support. |
| 1197 return; |
| 1198 } |
1102 view = /** @type {!i18n.input.chrome.inputview.elements.content. | 1199 view = /** @type {!i18n.input.chrome.inputview.elements.content. |
1103 MenuItem} */ (view); | 1200 MenuItem} */ (view); |
1104 if (e.type == EventType.POINTER_UP) { | 1201 if (e.type == EventType.POINTER_UP) { |
1105 this.executeCommand_.apply(this, view.getCommand()); | 1202 this.executeCommand_.apply(this, view.getCommand()); |
1106 this.container_.menuView.hide(); | 1203 this.container_.menuView.hide(); |
1107 this.soundController_.onKeyUp(view.type); | 1204 this.soundController_.onKeyUp(view.type); |
1108 this.resetAll(); | 1205 this.resetAll(); |
1109 } | 1206 } |
1110 view.setHighlighted(e.type == EventType.POINTER_DOWN || | 1207 view.setHighlighted(e.type == EventType.POINTER_DOWN || |
1111 e.type == EventType.POINTER_OVER); | 1208 e.type == EventType.POINTER_OVER); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1167 case ElementType.DRAG: | 1264 case ElementType.DRAG: |
1168 if (e.type == EventType.POINTER_DOWN && this.container_.floatingView) { | 1265 if (e.type == EventType.POINTER_DOWN && this.container_.floatingView) { |
1169 this.container_.floatingView.show(); | 1266 this.container_.floatingView.show(); |
1170 } | 1267 } |
1171 return; | 1268 return; |
1172 case ElementType.FLOATING_VIEW: | 1269 case ElementType.FLOATING_VIEW: |
1173 if (e.type == EventType.POINTER_UP && this.container_.floatingView) { | 1270 if (e.type == EventType.POINTER_UP && this.container_.floatingView) { |
1174 this.container_.floatingView.hide(); | 1271 this.container_.floatingView.hide(); |
1175 } | 1272 } |
1176 return; | 1273 return; |
1177 case ElementType.RESIZE: | |
1178 if (e.type == EventType.POINTER_UP) { | |
1179 goog.dom.classlist.toggle(this.container_.getElement(), Css.SMALL); | |
1180 this.resize(); | |
1181 } | |
1182 return; | |
1183 case ElementType.CUT: | 1274 case ElementType.CUT: |
1184 case ElementType.COPY: | 1275 case ElementType.COPY: |
1185 case ElementType.PASTE: | 1276 case ElementType.PASTE: |
1186 case ElementType.BOLD: | 1277 case ElementType.BOLD: |
1187 case ElementType.ITALICS: | 1278 case ElementType.ITALICS: |
1188 case ElementType.UNDERLINE: | 1279 case ElementType.UNDERLINE: |
1189 case ElementType.REDO: | 1280 case ElementType.REDO: |
1190 case ElementType.UNDO: | 1281 case ElementType.UNDO: |
1191 case ElementType.SELECT_ALL: | 1282 case ElementType.SELECT_ALL: |
1192 view.setHighlighted(e.type == EventType.POINTER_DOWN || | 1283 view.setHighlighted(e.type == EventType.POINTER_DOWN || |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1369 } else if (e.type == EventType.POINTER_UP) { | 1460 } else if (e.type == EventType.POINTER_UP) { |
1370 this.adapter_.sendKeyUpEvent('', KeyCodes.ARROW_RIGHT); | 1461 this.adapter_.sendKeyUpEvent('', KeyCodes.ARROW_RIGHT); |
1371 } | 1462 } |
1372 break; | 1463 break; |
1373 case ElementType.EN_SWITCHER: | 1464 case ElementType.EN_SWITCHER: |
1374 if (e.type == EventType.POINTER_UP) { | 1465 if (e.type == EventType.POINTER_UP) { |
1375 key = /** @type {!i18n.input.chrome.inputview.elements.content. | 1466 key = /** @type {!i18n.input.chrome.inputview.elements.content. |
1376 EnSwitcherKey} */ (softKey); | 1467 EnSwitcherKey} */ (softKey); |
1377 this.adapter_.toggleLanguageState(this.model_.stateManager.isEnMode); | 1468 this.adapter_.toggleLanguageState(this.model_.stateManager.isEnMode); |
1378 this.model_.stateManager.isEnMode = !this.model_.stateManager.isEnMode; | 1469 this.model_.stateManager.isEnMode = !this.model_.stateManager.isEnMode; |
1379 key.update(); | 1470 if (!this.updateToggleLanguageKeyset_()) { |
| 1471 key.update(); |
| 1472 } |
1380 } | 1473 } |
1381 break; | 1474 break; |
1382 case ElementType.SPACE_KEY: | 1475 case ElementType.SPACE_KEY: |
1383 key = /** @type {!i18n.input.chrome.inputview.elements.content. | 1476 key = /** @type {!i18n.input.chrome.inputview.elements.content. |
1384 SpaceKey} */ (softKey); | 1477 SpaceKey} */ (softKey); |
1385 var doubleSpacePeriod = this.model_.settings.doubleSpacePeriod && | 1478 var doubleSpacePeriod = this.model_.settings.doubleSpacePeriod && |
1386 this.currentKeyset_ != Controller.HANDWRITING_VIEW_CODE_ && | 1479 this.currentKeyset_ != Controller.HANDWRITING_VIEW_CODE_ && |
1387 this.currentKeyset_ != Controller.EMOJI_VIEW_CODE_; | 1480 this.currentKeyset_ != Controller.EMOJI_VIEW_CODE_; |
1388 if (e.type == EventType.POINTER_UP || (!doubleSpacePeriod && e.type == | 1481 if (e.type == EventType.POINTER_UP || (!doubleSpacePeriod && e.type == |
1389 EventType.DOUBLE_CLICK_END)) { | 1482 EventType.DOUBLE_CLICK_END)) { |
1390 this.adapter_.sendKeyDownAndUpEvent(key.getCharacter(), | 1483 this.adapter_.sendKeyDownAndUpEvent(key.getCharacter(), |
1391 KeyCodes.SPACE); | 1484 KeyCodes.SPACE); |
1392 this.clearUnstickyState_(); | 1485 this.clearUnstickyState_(); |
1393 } else if (e.type == EventType.DOUBLE_CLICK && doubleSpacePeriod) { | 1486 } else if (e.type == EventType.DOUBLE_CLICK && doubleSpacePeriod) { |
1394 this.adapter_.doubleClickOnSpaceKey(); | 1487 this.adapter_.doubleClickOnSpaceKey(); |
1395 } | 1488 } |
1396 if (this.returnToLetterKeysetOnSpace_) { | 1489 if (this.returnToLetterKeysetOnSpace_) { |
1397 // Return to the letter keyset. | 1490 // Return to the letter keyset. |
1398 this.switchToKeyset(key.toKeyset); | 1491 this.switchToKeyset(key.toKeyset); |
1399 this.returnToLetterKeysetOnSpace_ = false; | 1492 this.returnToLetterKeysetOnSpace_ = false; |
1400 } | 1493 } |
| 1494 var isHwt = Controller.HANDWRITING_VIEW_CODE_ == this.currentKeyset_; |
| 1495 if (isHwt) { |
| 1496 this.container_.cleanStroke(); |
| 1497 } |
1401 break; | 1498 break; |
1402 | 1499 |
1403 case ElementType.SWITCHER_KEY: | 1500 case ElementType.SWITCHER_KEY: |
1404 key = /** @type {!i18n.input.chrome.inputview.elements.content. | 1501 key = /** @type {!i18n.input.chrome.inputview.elements.content. |
1405 SwitcherKey} */ (softKey); | 1502 SwitcherKey} */ (softKey); |
1406 if (e.type == EventType.POINTER_UP) { | 1503 if (e.type == EventType.POINTER_UP) { |
1407 this.recordStatsForClosing_( | 1504 this.recordStatsForClosing_( |
1408 'InputMethod.VirtualKeyboard.LayoutSwitch', 1, 25, 25); | 1505 'InputMethod.VirtualKeyboard.LayoutSwitch', 1, 25, 25); |
1409 if (this.isSubKeyset_(key.toKeyset, this.currentKeyset_)) { | 1506 if (this.isSubKeyset_(key.toKeyset, this.currentKeyset_)) { |
1410 this.model_.stateManager.reset(); | 1507 this.model_.stateManager.reset(); |
(...skipping 18 matching lines...) Expand all Loading... |
1429 key = /** @type {!i18n.input.chrome.inputview.elements.content. | 1526 key = /** @type {!i18n.input.chrome.inputview.elements.content. |
1430 CompactKey} */(softKey); | 1527 CompactKey} */(softKey); |
1431 if (e.type == EventType.LONG_PRESS) { | 1528 if (e.type == EventType.LONG_PRESS) { |
1432 this.container_.altDataView.show( | 1529 this.container_.altDataView.show( |
1433 key, goog.i18n.bidi.isRtlLanguage(this.languageCode_), | 1530 key, goog.i18n.bidi.isRtlLanguage(this.languageCode_), |
1434 e.identifier); | 1531 e.identifier); |
1435 } else if (e.type == EventType.POINTER_UP) { | 1532 } else if (e.type == EventType.POINTER_UP) { |
1436 this.model_.stateManager.triggerChording(); | 1533 this.model_.stateManager.triggerChording(); |
1437 var ch = key.getActiveCharacter(); | 1534 var ch = key.getActiveCharacter(); |
1438 if (ch.length == 1) { | 1535 if (ch.length == 1) { |
1439 this.adapter_.sendKeyDownAndUpEvent(key.getActiveCharacter(), '', 0, | 1536 if (this.currentKeyset_.indexOf('symbol') != -1) { |
| 1537 this.adapter_.sendKeyDownAndUpEvent(key.getActiveCharacter(), |
| 1538 KeyCodes.SYMBOL, 0, this.getSpatialData_(key, e.x, e.y)); |
| 1539 } |
| 1540 else { |
| 1541 this.adapter_.sendKeyDownAndUpEvent(key.getActiveCharacter(), '', 0, |
1440 this.getSpatialData_(key, e.x, e.y)); | 1542 this.getSpatialData_(key, e.x, e.y)); |
| 1543 } |
1441 } else if (ch.length > 1) { | 1544 } else if (ch.length > 1) { |
1442 // Some compact keys contains more than 1 characters, such as '.com', | 1545 // Some compact keys contains more than 1 characters, such as '.com', |
1443 // 'http://', etc. Those keys should trigger a direct commit text | 1546 // 'http://', etc. Those keys should trigger a direct commit text |
1444 // instead of key events. | 1547 // instead of key events. |
1445 this.adapter_.commitText(ch); | 1548 this.adapter_.commitText(ch); |
1446 } | 1549 } |
1447 this.clearUnstickyState_(); | 1550 this.clearUnstickyState_(); |
1448 key.flickerredCharacter = ''; | 1551 key.flickerredCharacter = ''; |
1449 if (this.currentKeyset_.indexOf('symbol') != -1) { | 1552 if (this.currentKeyset_.indexOf('symbol') != -1) { |
1450 // If this is the symbol keyset, a space as the next input should | 1553 // If this is the symbol keyset, a space as the next input should |
(...skipping 17 matching lines...) Expand all Loading... |
1468 key = /** @type {!i18n.input.chrome.inputview.elements.content. | 1571 key = /** @type {!i18n.input.chrome.inputview.elements.content. |
1469 MenuKey} */ (softKey); | 1572 MenuKey} */ (softKey); |
1470 if (e.type == EventType.POINTER_DOWN) { | 1573 if (e.type == EventType.POINTER_DOWN) { |
1471 var isCompact = this.currentKeyset_.indexOf('compact') != -1; | 1574 var isCompact = this.currentKeyset_.indexOf('compact') != -1; |
1472 // Gets the default full keyboard instead of default keyset because | 1575 // Gets the default full keyboard instead of default keyset because |
1473 // the default keyset can be a compact keyset which would cause problem | 1576 // the default keyset can be a compact keyset which would cause problem |
1474 // in MenuView.show(). | 1577 // in MenuView.show(). |
1475 var defaultFullKeyset = this.initialKeyset_.split(/\./)[0]; | 1578 var defaultFullKeyset = this.initialKeyset_.split(/\./)[0]; |
1476 var enableCompact = !this.adapter_.isA11yMode && goog.array.contains( | 1579 var enableCompact = !this.adapter_.isA11yMode && goog.array.contains( |
1477 util.KEYSETS_HAVE_COMPACT, defaultFullKeyset); | 1580 util.KEYSETS_HAVE_COMPACT, defaultFullKeyset); |
1478 if (defaultFullKeyset == 'zhuyin' && | 1581 if (this.languageCode_ == 'ko') { |
1479 !this.adapter_.features.isEnabled(FeatureName.EXPERIMENTAL) || | |
1480 this.languageCode_ == 'ko') { | |
1481 // Hides 'switch to compact' for zhuyin when not in experimental env. | |
1482 enableCompact = false; | 1582 enableCompact = false; |
1483 } | 1583 } |
1484 var hasHwt = !this.adapter_.isPasswordBox() && | 1584 var hasHwt = !this.adapter_.isPasswordBox() && |
1485 !Controller.DISABLE_HWT && goog.object.contains( | 1585 !Controller.DISABLE_HWT && goog.object.contains( |
1486 InputToolCode, this.getHwtInputToolCode_()); | 1586 InputToolCode, this.getHwtInputToolCode_()); |
1487 var hasEmoji = !this.adapter_.isPasswordBox(); | 1587 var hasEmoji = !this.adapter_.isPasswordBox(); |
1488 var enableSettings = this.shouldEnableSettings() && | 1588 var enableSettings = this.shouldEnableSettings() && |
1489 !!window.inputview && !!inputview.openSettings; | 1589 !!window.inputview && !!inputview.openSettings; |
1490 var enableFVK = this.adapter_.isFloatingVirtualKeyboardEnabled(); | |
1491 this.adapter_.getInputMethods(function(inputMethods) { | 1590 this.adapter_.getInputMethods(function(inputMethods) { |
1492 this.container_.menuView.show(key, defaultFullKeyset, isCompact, | 1591 this.container_.menuView.show(key, defaultFullKeyset, isCompact, |
1493 enableCompact, this.currentInputMethod_, inputMethods, hasHwt, | 1592 enableCompact, this.currentInputMethod_, inputMethods, hasHwt, |
1494 enableSettings, hasEmoji, this.adapter_.isA11yMode, enableFVK, | 1593 enableSettings, hasEmoji, this.adapter_.isA11yMode); |
1495 this.adapter_.isFloating); | |
1496 }.bind(this)); | 1594 }.bind(this)); |
1497 } | 1595 } |
1498 break; | 1596 break; |
1499 | 1597 |
1500 case ElementType.GLOBE_KEY: | 1598 case ElementType.GLOBE_KEY: |
1501 if (e.type == EventType.POINTER_UP) { | 1599 if (e.type == EventType.POINTER_UP) { |
1502 this.adapter_.clearModifierStates(); | 1600 this.adapter_.clearModifierStates(); |
1503 this.adapter_.setModifierState( | 1601 this.adapter_.setModifierState( |
1504 i18n.input.chrome.inputview.StateType.ALT, true); | 1602 i18n.input.chrome.inputview.StateType.ALT, true); |
1505 this.adapter_.sendKeyDownAndUpEvent( | 1603 this.adapter_.sendKeyDownAndUpEvent( |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1553 } | 1651 } |
1554 }; | 1652 }; |
1555 | 1653 |
1556 | 1654 |
1557 /** | 1655 /** |
1558 * The tick for the backspace key. | 1656 * The tick for the backspace key. |
1559 * | 1657 * |
1560 * @private | 1658 * @private |
1561 */ | 1659 */ |
1562 Controller.prototype.backspaceTick_ = function() { | 1660 Controller.prototype.backspaceTick_ = function() { |
1563 if (this.backspaceRepeated_ >= Controller.BACKSPACE_REPEAT_LIMIT_) { | |
1564 this.stopBackspaceAutoRepeat_(); | |
1565 return; | |
1566 } | |
1567 this.backspaceRepeated_++; | 1661 this.backspaceRepeated_++; |
1568 this.backspaceDown_(); | 1662 this.backspaceDown_(); |
1569 this.soundController_.onKeyRepeat(ElementType.BACKSPACE_KEY); | 1663 this.soundController_.onKeyRepeat(ElementType.BACKSPACE_KEY); |
1570 | 1664 |
1571 if (this.backspaceAutoRepeat_) { | 1665 if (this.backspaceAutoRepeat_) { |
1572 this.backspaceAutoRepeat_.start(75); | 1666 var delay = MINIMUM_BACKSPACE_REPEAT_TIME_MS; |
| 1667 if (this.backspaceRepeated_ <= BACKSPACE_REPEAT_LIMIT) { |
| 1668 var ease = goog.fx.easing.easeOut( |
| 1669 this.backspaceRepeated_ / BACKSPACE_REPEAT_LIMIT); |
| 1670 var delta = MAXIMUM_BACKSPACE_REPEAT_TIME_MS - |
| 1671 MINIMUM_BACKSPACE_REPEAT_TIME_MS; |
| 1672 delay = MAXIMUM_BACKSPACE_REPEAT_TIME_MS - (delta * ease); |
| 1673 } |
| 1674 this.backspaceAutoRepeat_.start(delay); |
1573 } else { | 1675 } else { |
1574 this.backspaceAutoRepeat_ = new goog.async.Delay( | 1676 this.backspaceAutoRepeat_ = new goog.async.Delay( |
1575 goog.bind(this.backspaceTick_, this), 300); | 1677 goog.bind(this.backspaceTick_, this), |
| 1678 BACKSPACE_REPEAT_START_TIME_MS); |
1576 this.backspaceAutoRepeat_.start(); | 1679 this.backspaceAutoRepeat_.start(); |
1577 } | 1680 } |
1578 }; | 1681 }; |
1579 | 1682 |
1580 | 1683 |
1581 /** | 1684 /** |
1582 * Callback for VISIBILITY_CHANGE. | 1685 * Callback for VISIBILITY_CHANGE. |
1583 * | 1686 * |
1584 * @private | 1687 * @private |
1585 */ | 1688 */ |
(...skipping 20 matching lines...) Expand all Loading... |
1606 this.clearCandidates_(); | 1709 this.clearCandidates_(); |
1607 this.container_.cleanStroke(); | 1710 this.container_.cleanStroke(); |
1608 this.model_.stateManager.reset(); | 1711 this.model_.stateManager.reset(); |
1609 this.container_.update(); | 1712 this.container_.update(); |
1610 this.updateContextModifierState_(); | 1713 this.updateContextModifierState_(); |
1611 this.resize(); | 1714 this.resize(); |
1612 this.container_.expandedCandidateView.close(); | 1715 this.container_.expandedCandidateView.close(); |
1613 this.container_.menuView.hide(); | 1716 this.container_.menuView.hide(); |
1614 this.container_.swipeView.reset(); | 1717 this.container_.swipeView.reset(); |
1615 this.container_.altDataView.hide(); | 1718 this.container_.altDataView.hide(); |
1616 this.container_.gesturePreviewView.hide(); | 1719 if (this.container_.gesturePreviewWindow) { |
| 1720 this.container_.gesturePreviewWindow.hide(); |
| 1721 } |
1617 if (this.container_.floatingView) { | 1722 if (this.container_.floatingView) { |
1618 this.container_.floatingView.hide(); | 1723 this.container_.floatingView.hide(); |
1619 } | 1724 } |
| 1725 this.stopBackspaceAutoRepeat_(); |
1620 }; | 1726 }; |
1621 | 1727 |
1622 | 1728 |
1623 /** | 1729 /** |
1624 * Returns whether the toolbar should be shown. | 1730 * Returns whether the toolbar should be shown. |
1625 * | 1731 * |
1626 * @return {boolean} | 1732 * @return {boolean} |
1627 * @private | 1733 * @private |
1628 */ | 1734 */ |
1629 Controller.prototype.shouldShowToolBar_ = function() { | 1735 Controller.prototype.shouldShowToolBar_ = function() { |
(...skipping 18 matching lines...) Expand all Loading... |
1648 /** | 1754 /** |
1649 * Callback when surrounding text is changed. | 1755 * Callback when surrounding text is changed. |
1650 * | 1756 * |
1651 * @param {!i18n.input.chrome.inputview.events.SurroundingTextChangedEvent} e . | 1757 * @param {!i18n.input.chrome.inputview.events.SurroundingTextChangedEvent} e . |
1652 * @private | 1758 * @private |
1653 */ | 1759 */ |
1654 Controller.prototype.onSurroundingTextChanged_ = function(e) { | 1760 Controller.prototype.onSurroundingTextChanged_ = function(e) { |
1655 if (!this.model_.settings.autoCapital || !e.text) { | 1761 if (!this.model_.settings.autoCapital || !e.text) { |
1656 return; | 1762 return; |
1657 } | 1763 } |
1658 | 1764 var textBeforeCursor = e.textBeforeCursor.replace(/\u00a0/g, ' '); |
1659 var isShiftEnabled = this.model_.stateManager.hasState(StateType.SHIFT); | 1765 var isShiftEnabled = this.model_.stateManager.hasState(StateType.SHIFT); |
1660 var needAutoCap = this.model_.settings.autoCapital && | 1766 var needAutoCap = this.model_.settings.autoCapital && |
1661 util.needAutoCap(e.text); | 1767 util.needAutoCap(textBeforeCursor); |
1662 if (needAutoCap && !isShiftEnabled) { | 1768 if (needAutoCap && !isShiftEnabled) { |
1663 this.changeState_(StateType.SHIFT, true, false); | 1769 this.changeState_(StateType.SHIFT, true, false); |
1664 this.shiftForAutoCapital_ = true; | 1770 this.shiftForAutoCapital_ = true; |
1665 } else if (!needAutoCap && this.shiftForAutoCapital_) { | 1771 } else if (!needAutoCap && this.shiftForAutoCapital_) { |
1666 this.changeState_(StateType.SHIFT, false, false); | 1772 this.changeState_(StateType.SHIFT, false, false); |
1667 } | 1773 } |
1668 }; | 1774 }; |
1669 | 1775 |
1670 | 1776 |
1671 /** | 1777 /** |
1672 * Callback for Context blurs. | 1778 * Callback for Context blurs. |
1673 * | 1779 * |
1674 * @private | 1780 * @private |
1675 */ | 1781 */ |
1676 Controller.prototype.onContextBlur_ = function() { | 1782 Controller.prototype.onContextBlur_ = function() { |
1677 this.container_.cleanStroke(); | 1783 this.container_.cleanStroke(); |
1678 this.container_.menuView.hide(); | 1784 this.container_.menuView.hide(); |
| 1785 this.stopBackspaceAutoRepeat_(); |
1679 }; | 1786 }; |
1680 | 1787 |
1681 | 1788 |
1682 /** | 1789 /** |
1683 * Backspace key is down. | 1790 * Backspace key is down. |
1684 * | 1791 * |
1685 * @private | 1792 * @private |
1686 */ | 1793 */ |
1687 Controller.prototype.backspaceDown_ = function() { | 1794 Controller.prototype.backspaceDown_ = function() { |
1688 if (this.container_.hasStrokesOnCanvas()) { | 1795 if (this.container_.hasStrokesOnCanvas()) { |
1689 this.clearCandidates_(); | 1796 this.clearCandidates_(); |
1690 this.container_.cleanStroke(); | 1797 this.container_.cleanStroke(); |
1691 } else { | 1798 } else { |
1692 this.adapter_.sendKeyDownEvent('\u0008', KeyCodes.BACKSPACE); | 1799 this.adapter_.sendKeyDownEvent('\u0008', KeyCodes.BACKSPACE); |
1693 } | 1800 } |
1694 this.recordStatsForClosing_( | 1801 this.recordStatsForClosing_( |
1695 'InputMethod.VirtualKeyboard.BackspaceCount', 1, 4095, 4096); | 1802 'InputMethod.VirtualKeyboard.BackspaceCount', 1, 4095, 4096); |
1696 this.statistics_.recordEnum('InputMethod.VirtualKeyboard.BackspaceOnLayout', | 1803 this.statistics_.recordEnum('InputMethod.VirtualKeyboard.BackspaceOnLayout', |
1697 this.statistics_.getLayoutType(this.currentKeyset_, | 1804 this.statistics_.getLayoutType(this.currentKeyset_, |
1698 this.adapter_.isA11yMode), | 1805 this.adapter_.isA11yMode), |
1699 i18n.input.chrome.Statistics.LayoutTypes.MAX); | 1806 Statistics.LayoutTypes.MAX); |
1700 }; | 1807 }; |
1701 | 1808 |
1702 | 1809 |
1703 /** | 1810 /** |
1704 * Callback for state change. | 1811 * Callback for state change. |
1705 * | 1812 * |
1706 * @param {StateType} stateType The state type. | 1813 * @param {StateType} stateType The state type. |
1707 * @param {boolean} enable True to enable the state. | 1814 * @param {boolean} enable True to enable the state. |
1708 * @param {boolean} isSticky True to make the state sticky. | 1815 * @param {boolean} isSticky True to make the state sticky. |
1709 * @param {boolean=} opt_isFinalSticky . | 1816 * @param {boolean=} opt_isFinalSticky . |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1767 */ | 1874 */ |
1768 Controller.prototype.onCandidatesBack_ = function(e) { | 1875 Controller.prototype.onCandidatesBack_ = function(e) { |
1769 this.candidatesInfo_ = new i18n.input.chrome.inputview.CandidatesInfo( | 1876 this.candidatesInfo_ = new i18n.input.chrome.inputview.CandidatesInfo( |
1770 e.source, e.candidates); | 1877 e.source, e.candidates); |
1771 this.showCandidates_(e.source, e.candidates, Controller.CandidatesOperation. | 1878 this.showCandidates_(e.source, e.candidates, Controller.CandidatesOperation. |
1772 NONE); | 1879 NONE); |
1773 }; | 1880 }; |
1774 | 1881 |
1775 | 1882 |
1776 /** | 1883 /** |
| 1884 * Converts a word to shifted or all-caps based on the current shift state. |
| 1885 * |
| 1886 * @param {string} word The word to potentially convert. |
| 1887 * @return {string} The converted word. |
| 1888 * @private |
| 1889 */ |
| 1890 Controller.prototype.convertToShifted_ = function(word) { |
| 1891 if (this.model_.stateManager.getState() == StateType.SHIFT) { |
| 1892 if (this.model_.stateManager.isSticky(StateType.SHIFT) && |
| 1893 this.model_.stateManager.isFinalSticky(StateType.SHIFT)) { |
| 1894 word = word.toUpperCase(); |
| 1895 } else { |
| 1896 word = word.charAt(0).toUpperCase() + word.slice(1); |
| 1897 } |
| 1898 } |
| 1899 return word; |
| 1900 }; |
| 1901 |
| 1902 |
| 1903 /** |
1777 * Callback for gestures results event. | 1904 * Callback for gestures results event. |
1778 * | 1905 * |
1779 * @param {!i18n.input.chrome.DataSource.GesturesBackEvent} e . | 1906 * @param {!i18n.input.chrome.DataSource.GesturesBackEvent} e . |
1780 * @private | 1907 * @private |
1781 */ | 1908 */ |
1782 Controller.prototype.onGesturesBack_ = function(e) { | 1909 Controller.prototype.onGesturesBack_ = function(e) { |
1783 if (!this.commitNextGestureResult_ && | 1910 var response = e.response; |
1784 goog.array.equals(e.results, this.gestureResultsCache_)) { | 1911 this.stopBackspaceAutoRepeat_(); |
| 1912 if (!response.commit && |
| 1913 goog.array.equals(response.results, this.gestureResultsCache_)) { |
1785 // If gesture results have not updated, do not transmit to the UI. | 1914 // If gesture results have not updated, do not transmit to the UI. |
1786 return; | 1915 return; |
1787 } else { | 1916 } else { |
1788 this.gestureResultsCache_ = e.results; | 1917 this.gestureResultsCache_ = response.results; |
1789 } | 1918 } |
1790 var bestResult = e.results[0]; | 1919 var bestResult = this.convertToShifted_(response.results[0]); |
1791 if (this.container_.gesturePreviewView) { | 1920 if (this.container_.gesturePreviewWindow && |
1792 this.container_.gesturePreviewView.show(bestResult); | 1921 this.container_.gestureCanvasView.isGesturing) { |
| 1922 this.container_.gesturePreviewWindow.show(bestResult); |
1793 } | 1923 } |
1794 // TODO: Resolve a race where multiple decoder results return after this flag | 1924 if (response.commit) { |
1795 // is set to true. | |
1796 if (this.commitNextGestureResult_) { | |
1797 // Commit the best result. | 1925 // Commit the best result. |
1798 this.adapter_.commitGestureResult(bestResult); | 1926 this.adapter_.commitGestureResult( |
1799 this.commitNextGestureResult_ = false; | 1927 bestResult, this.adapter_.isGoogleDocument()); |
1800 this.gestureResultsCache_ = []; | 1928 this.gestureResultsCache_ = []; |
| 1929 this.statistics_.recordEnum( |
| 1930 Statistics.GESTURE_TYPING_METRIC_NAME, |
| 1931 Statistics.GestureTypingEvent.TYPED, |
| 1932 Statistics.GestureTypingEvent.MAX); |
| 1933 if (this.container_.gesturePreviewWindow) { |
| 1934 new goog.async.Delay( |
| 1935 goog.bind(this.container_.gesturePreviewWindow.hide, |
| 1936 this.container_.gesturePreviewWindow), |
| 1937 GESTURE_PREVIEW_LINGER_TIME_MS).start(); |
| 1938 } |
1801 } | 1939 } |
1802 this.showGestureCandidates_(e.results.slice(1)); | 1940 this.showGestureCandidates_(response.results.slice(1)); |
1803 }; | 1941 }; |
1804 | 1942 |
1805 | 1943 |
1806 /** | 1944 /** |
1807 * Shows the gesture results as candidates. | 1945 * Shows the gesture results as candidates. |
1808 * | 1946 * |
1809 * @param {!Array<string>} results The gesture results to show. | 1947 * @param {!Array<string>} results The gesture results to show. |
1810 * @private | 1948 * @private |
1811 */ | 1949 */ |
1812 Controller.prototype.showGestureCandidates_ = function(results) { | 1950 Controller.prototype.showGestureCandidates_ = function(results) { |
1813 // Convert the results to the candidate format. | 1951 // Convert the results to the candidate format. |
1814 var candidates = []; | 1952 var candidates = []; |
1815 for (var i = 0; i < results.length; ++i) { | 1953 for (var i = 0; i < results.length; ++i) { |
1816 var candidate = {}; | 1954 var candidate = {}; |
1817 candidate[Name.CANDIDATE] = results[i]; | 1955 var result = this.convertToShifted_(results[i]); |
| 1956 candidate[Name.CANDIDATE] = result; |
1818 candidate[Name.CANDIDATE_ID] = i; | 1957 candidate[Name.CANDIDATE_ID] = i; |
1819 candidate[Name.IS_EMOJI] = false; | 1958 candidate[Name.IS_EMOJI] = false; |
1820 candidate[Name.MATCHED_LENGTHS] = 0; | 1959 candidate[Name.MATCHED_LENGTHS] = 0; |
1821 candidates.push(candidate); | 1960 candidates.push(candidate); |
1822 } | 1961 } |
1823 // The source is empty as this is a gesture and not a series of key presses. | 1962 // The source is empty as this is a gesture and not a series of key presses. |
1824 this.showCandidates_('', candidates, Controller.CandidatesOperation.NONE); | 1963 this.showCandidates_( |
| 1964 '', candidates, Controller.CandidatesOperation.NONE, true); |
1825 }; | 1965 }; |
1826 | 1966 |
1827 | 1967 |
1828 /** | 1968 /** |
1829 * Shows the candidates to the candidate view. | 1969 * Shows the candidates to the candidate view. |
1830 * | 1970 * |
1831 * @param {string} source The source text. | 1971 * @param {string} source The source text. |
1832 * @param {!Array.<!Object>} candidates The candidate text list. | 1972 * @param {!Array.<!Object>} candidates The candidate text list. |
1833 * @param {Controller.CandidatesOperation} operation . | 1973 * @param {Controller.CandidatesOperation} operation . |
| 1974 * @param {boolean=} opt_fromGestures Whether or not the candidates are being |
| 1975 * set by gesture typing. |
1834 * @private | 1976 * @private |
1835 */ | 1977 */ |
1836 Controller.prototype.showCandidates_ = function(source, candidates, | 1978 Controller.prototype.showCandidates_ = function(source, candidates, |
1837 operation) { | 1979 operation, opt_fromGestures) { |
1838 var state = !!source ? ExpandedCandidateView.State.COMPLETION_CORRECTION : | 1980 var state = !!source ? ExpandedCandidateView.State.COMPLETION_CORRECTION : |
1839 ExpandedCandidateView.State.PREDICTION; | 1981 ExpandedCandidateView.State.PREDICTION; |
1840 var expandView = this.container_.expandedCandidateView; | 1982 var expandView = this.container_.expandedCandidateView; |
1841 var expand = false; | 1983 var expand = false; |
1842 if (operation == Controller.CandidatesOperation.NONE) { | 1984 if (operation == Controller.CandidatesOperation.NONE) { |
1843 expand = expandView.state == state; | 1985 expand = expandView.state == state; |
1844 } else { | 1986 } else { |
1845 expand = operation == Controller.CandidatesOperation.EXPAND; | 1987 expand = operation == Controller.CandidatesOperation.EXPAND; |
1846 } | 1988 } |
1847 | 1989 |
(...skipping 28 matching lines...) Expand all Loading... |
1876 this.container_.candidateView.candidateCount); | 2018 this.container_.candidateView.candidateCount); |
1877 this.container_.candidateView.switchToIcon(CandidateView.IconType. | 2019 this.container_.candidateView.switchToIcon(CandidateView.IconType. |
1878 SHRINK_CANDIDATES, true); | 2020 SHRINK_CANDIDATES, true); |
1879 } else { | 2021 } else { |
1880 expandView.state = ExpandedCandidateView.State.NONE; | 2022 expandView.state = ExpandedCandidateView.State.NONE; |
1881 expandView.setVisible(false); | 2023 expandView.setVisible(false); |
1882 this.container_.candidateView.switchToIcon(CandidateView.IconType. | 2024 this.container_.candidateView.switchToIcon(CandidateView.IconType. |
1883 SHRINK_CANDIDATES, false); | 2025 SHRINK_CANDIDATES, false); |
1884 this.container_.currentKeysetView.setVisible(true); | 2026 this.container_.currentKeysetView.setVisible(true); |
1885 } | 2027 } |
| 2028 this.candidatesSetByGestureTyping_ = !!opt_fromGestures; |
1886 }; | 2029 }; |
1887 | 2030 |
1888 | 2031 |
1889 /** | 2032 /** |
1890 * Clears candidates. | 2033 * Clears candidates. |
1891 * | 2034 * |
1892 * @private | 2035 * @private |
1893 */ | 2036 */ |
1894 Controller.prototype.clearCandidates_ = function() { | 2037 Controller.prototype.clearCandidates_ = function() { |
1895 this.candidatesInfo_ = i18n.input.chrome.inputview.CandidatesInfo.getEmpty(); | 2038 this.candidatesInfo_ = i18n.input.chrome.inputview.CandidatesInfo.getEmpty(); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1984 var created = false; | 2127 var created = false; |
1985 if (this.keysetDataMap_[remappedActiveKeyset]) { | 2128 if (this.keysetDataMap_[remappedActiveKeyset]) { |
1986 this.createView_(remappedActiveKeyset); | 2129 this.createView_(remappedActiveKeyset); |
1987 this.switchToKeyset(activeKeyset); | 2130 this.switchToKeyset(activeKeyset); |
1988 created = true; | 2131 created = true; |
1989 } | 2132 } |
1990 // Async creating the non-active keysets to reduce the latency of showing the | 2133 // Async creating the non-active keysets to reduce the latency of showing the |
1991 // active keyset. | 2134 // active keyset. |
1992 var keyLen = Object.keys(this.keysetDataMap_).length; | 2135 var keyLen = Object.keys(this.keysetDataMap_).length; |
1993 if (created && keyLen > 1 || !created && keyLen > 0) { | 2136 if (created && keyLen > 1 || !created && keyLen > 0) { |
1994 goog.Timer.callOnce((function() { | 2137 if (Controller.DISABLE_DELAY_LOADING_FOR_TEST) { |
1995 for (var keyset in this.keysetDataMap_) { | 2138 for (var keyset in this.keysetDataMap_) { |
1996 this.createView_(keyset); | 2139 this.createView_(keyset); |
1997 } | 2140 } |
1998 }).bind(this)); | 2141 } else { |
| 2142 goog.Timer.callOnce((function() { |
| 2143 for (var keyset in this.keysetDataMap_) { |
| 2144 this.createView_(keyset); |
| 2145 } |
| 2146 }).bind(this)); |
| 2147 } |
1999 } | 2148 } |
2000 }; | 2149 }; |
2001 | 2150 |
2002 | 2151 |
2003 /** | 2152 /** |
2004 * Switch to a specific keyboard. | 2153 * Switch to a specific keyboard. |
2005 * | 2154 * |
2006 * @param {string} keyset The keyset name. | 2155 * @param {string} keyset The keyset name. |
2007 */ | 2156 */ |
2008 Controller.prototype.switchToKeyset = function(keyset) { | 2157 Controller.prototype.switchToKeyset = function(keyset) { |
2009 if (!this.isSettingReady || this.adapter_.isSwitching()) { | 2158 if (!this.isSettingReady || this.adapter_.isSwitching()) { |
2010 return; | 2159 return; |
2011 } | 2160 } |
2012 | 2161 |
2013 var contextType = this.adapter_.contextType; | 2162 var contextType = this.adapter_.contextType; |
2014 var ret = this.container_.switchToKeyset(this.getRemappedKeyset_(keyset), | 2163 var ret = this.container_.switchToKeyset(this.getRemappedKeyset_(keyset), |
2015 this.title_, this.adapter_.isPasswordBox(), this.adapter_.isA11yMode, | 2164 this.title_, this.adapter_.isPasswordBox(), this.adapter_.isA11yMode, |
2016 keyset, this.contextTypeToLastKeysetMap_[contextType] || | 2165 keyset, this.contextTypeToLastKeysetMap_[contextType] || |
2017 this.getActiveKeyset_(), this.languageCode_); | 2166 this.getActiveKeyset_(), this.languageCode_); |
2018 | 2167 |
| 2168 // If it is the sub keyset switching, emoji, or in hotrod mode, don't record |
| 2169 // the keyset. |
| 2170 if (!this.isSubKeyset_(this.currentKeyset_, keyset) && |
| 2171 keyset != Controller.EMOJI_VIEW_CODE_ && |
| 2172 !this.adapter_.isHotrod) { |
| 2173 // Update the keyset of current context type. |
| 2174 this.contextTypeToKeysetMap_[this.currentInputMethod_][contextType] = |
| 2175 keyset; |
| 2176 } |
| 2177 |
2019 if (ret) { | 2178 if (ret) { |
2020 if (!this.isSubKeyset_(this.currentKeyset_, keyset) && | |
2021 keyset != Controller.EMOJI_VIEW_CODE_) { | |
2022 // If it is the sub keyset switching, or emoji, don't record it. | |
2023 // Update the keyset of current context type. | |
2024 this.contextTypeToKeysetMap_[this.currentInputMethod_][contextType] = | |
2025 keyset; | |
2026 } | |
2027 this.updateLanguageState_(this.currentKeyset_, keyset); | 2179 this.updateLanguageState_(this.currentKeyset_, keyset); |
2028 this.currentKeyset_ = keyset; | 2180 this.currentKeyset_ = keyset; |
2029 this.resize(Controller.DEV); | 2181 this.resize(Controller.DEV); |
2030 this.statistics_.recordLayout(keyset, this.adapter_.isA11yMode); | 2182 this.statistics_.recordLayout(keyset, this.adapter_.isA11yMode); |
2031 this.perfTracker_.tick(PerfTracker.TickName.KEYBOARD_SHOWN); | 2183 this.perfTracker_.tick(PerfTracker.TickName.KEYBOARD_SHOWN); |
2032 this.perfTracker_.stop(); | 2184 this.perfTracker_.stop(); |
2033 } else { | 2185 } else { |
2034 // Sets the current keyset for delay switching. | 2186 // Sets the current keyset for delay switching. |
2035 this.currentKeyset_ = keyset; | 2187 this.currentKeyset_ = keyset; |
2036 if (keyset != Controller.EMOJI_VIEW_CODE_) { // Emoji is temp keyset. | |
2037 this.contextTypeToKeysetMap_[this.currentInputMethod_][contextType] = | |
2038 keyset; | |
2039 } | |
2040 this.loadResource_(keyset); | 2188 this.loadResource_(keyset); |
2041 } | 2189 } |
2042 | 2190 |
2043 // TODO: The 'us' part of this code is a workaround an issue where other xkb | 2191 // TODO: The 'us' part of this code is a workaround an issue where other xkb |
2044 // languages seem to be sharing options between each other. | 2192 // languages seem to be sharing options between each other. |
2045 this.isKeysetUSCompact_ = | 2193 this.isKeysetUSCompact_ = |
2046 this.currentKeyset_.indexOf(Controller.US_COMPACT_PREFIX_) >= 0; | 2194 this.currentKeyset_.indexOf(Controller.US_COMPACT_QWERTY_CODE_) >= 0; |
2047 // If we're switching to a new keyset, we don't want spacebar to trigger | 2195 // If we're switching to a new keyset, we don't want spacebar to trigger |
2048 // another keyset switch. | 2196 // another keyset switch. |
2049 this.returnToLetterKeysetOnSpace_ = false; | 2197 this.returnToLetterKeysetOnSpace_ = false; |
| 2198 if (this.gestureTypingEnabled_()) { |
| 2199 this.container_.gestureCanvasView.clear(); |
| 2200 } |
2050 }; | 2201 }; |
2051 | 2202 |
2052 | 2203 |
2053 /** | 2204 /** |
2054 * Callback when the configuration is loaded. | 2205 * Callback when the configuration is loaded. |
2055 * | 2206 * |
2056 * @param {!i18n.input.chrome.inputview.events.ConfigLoadedEvent} e The event. | 2207 * @param {!i18n.input.chrome.inputview.events.ConfigLoadedEvent} e The event. |
2057 * @private | 2208 * @private |
2058 */ | 2209 */ |
2059 Controller.prototype.onConfigLoaded_ = function(e) { | 2210 Controller.prototype.onConfigLoaded_ = function(e) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2123 if (isWideScreen) { | 2274 if (isWideScreen) { |
2124 widthPercent = spec['LANDSCAPE_WIDE_SCREEN']; | 2275 widthPercent = spec['LANDSCAPE_WIDE_SCREEN']; |
2125 } else { | 2276 } else { |
2126 widthPercent = spec['LANDSCAPE']; | 2277 widthPercent = spec['LANDSCAPE']; |
2127 } | 2278 } |
2128 } else { | 2279 } else { |
2129 widthPercent = spec['PORTRAIT']; | 2280 widthPercent = spec['PORTRAIT']; |
2130 } | 2281 } |
2131 candidateViewHeight = SizeSpec.NON_A11Y_CANDIDATE_VIEW_HEIGHT; | 2282 candidateViewHeight = SizeSpec.NON_A11Y_CANDIDATE_VIEW_HEIGHT; |
2132 } | 2283 } |
2133 width = this.adapter_.isFloating ? | 2284 var isFloatingMode = this.adapter_.isFloatingVirtualKeyboardEnabled(); |
| 2285 width = isFloatingMode ? |
2134 Math.floor(screen.width * widthPercent) : screen.width; | 2286 Math.floor(screen.width * widthPercent) : screen.width; |
2135 widthPercent = this.adapter_.isFloating ? 1.0 : widthPercent; | 2287 widthPercent = isFloatingMode ? 1.0 : widthPercent; |
2136 if (goog.dom.classlist.contains(this.container_.getElement(), Css.SMALL)) { | 2288 |
2137 height = SizeSpec.SMALL_SIZE_HEIGHT; | 2289 // Floating virtual keyboard needs to be placed in the bottom of screen and |
2138 width = SizeSpec.SMALL_SIZE_WIDTH; | 2290 // centered when initially shows up. innerHeight == 0 is used as heuristic to |
2139 candidateViewHeight = SizeSpec.SMALL_SIZE_CANDIDATE_VIEW_HEIGHT; | 2291 // check if keyboard is showing up for the first time. |
| 2292 if (isFloatingMode && window.innerHeight == 0) { |
| 2293 window.moveTo((screen.width - width) / 2, screen.height - height); |
2140 } | 2294 } |
2141 | 2295 |
2142 if ((window.innerHeight != height || window.innerWidth != width) && | 2296 if ((window.innerHeight != height || window.innerWidth != width) && |
2143 !opt_preventResizeTo) { | 2297 !opt_preventResizeTo) { |
2144 if (this.lastResizeHeight_ != height || window.innerWidth != width) { | 2298 if (this.lastResizeHeight_ != height || window.innerWidth != width) { |
2145 this.lastResizeHeight_ = height; | 2299 this.lastResizeHeight_ = height; |
2146 window.resizeTo(width, height); | 2300 window.resizeTo(width, height); |
2147 } | 2301 } |
2148 return; | 2302 return; |
2149 } | 2303 } |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2392 * Handles language state changing event. | 2546 * Handles language state changing event. |
2393 * | 2547 * |
2394 * @param {!events.MessageEvent} e . | 2548 * @param {!events.MessageEvent} e . |
2395 * @private | 2549 * @private |
2396 */ | 2550 */ |
2397 Controller.prototype.onUpdateToggleLanguageState_ = function(e) { | 2551 Controller.prototype.onUpdateToggleLanguageState_ = function(e) { |
2398 if (this.adapter_.isA11yMode || this.currentKeyset_.indexOf('.compact') < 0) { | 2552 if (this.adapter_.isA11yMode || this.currentKeyset_.indexOf('.compact') < 0) { |
2399 // e.msg value means whether is Chinese mode now. | 2553 // e.msg value means whether is Chinese mode now. |
2400 if (this.model_.stateManager.isEnMode == e.msg) { | 2554 if (this.model_.stateManager.isEnMode == e.msg) { |
2401 this.model_.stateManager.isEnMode = !e.msg; | 2555 this.model_.stateManager.isEnMode = !e.msg; |
| 2556 this.updateToggleLanguageKeyset_(); |
2402 this.container_.currentKeysetView.update(); | 2557 this.container_.currentKeysetView.update(); |
2403 } | 2558 } |
2404 } else { | 2559 } else { |
2405 var pos = this.currentKeyset_.indexOf('en.compact'); | 2560 var pos = this.currentKeyset_.indexOf('en.compact'); |
2406 var toKeyset; | 2561 var toKeyset; |
2407 if (pos > 0) { // Means en mode | 2562 if (pos > 0) { // Means en mode |
2408 if (e.msg) { // Needs switch cn mode | 2563 if (e.msg) { // Needs switch cn mode |
2409 toKeyset = this.currentKeyset_.replace('en.compact', 'compact'); | 2564 toKeyset = this.currentKeyset_.replace('en.compact', 'compact'); |
2410 } | 2565 } |
2411 } else { | 2566 } else { |
2412 if (!e.msg) { // Needs switch en mode | 2567 if (!e.msg) { // Needs switch en mode |
2413 toKeyset = this.currentKeyset_.replace('compact', 'en.compact'); | 2568 toKeyset = this.currentKeyset_.replace('compact', 'en.compact'); |
2414 } | 2569 } |
2415 } | 2570 } |
2416 if (toKeyset) { | 2571 if (toKeyset) { |
2417 this.resetAll(); | 2572 this.resetAll(); |
2418 this.switchToKeyset(toKeyset); | 2573 this.switchToKeyset(toKeyset); |
2419 } | 2574 } |
2420 } | 2575 } |
2421 }; | 2576 }; |
| 2577 |
| 2578 |
| 2579 /** |
| 2580 * Update keyset when language state changes. |
| 2581 * |
| 2582 * @return {boolean} |
| 2583 * @private |
| 2584 */ |
| 2585 Controller.prototype.updateToggleLanguageKeyset_ = function() { |
| 2586 var pos = this.currentKeyset_.indexOf('.us'); |
| 2587 var toKeyset; |
| 2588 if (pos > 0) { |
| 2589 toKeyset = this.currentKeyset_.replace('.us', ''); |
| 2590 if (goog.array.contains(util.KEYSETS_SWITCH_WITH_US, toKeyset)) { |
| 2591 this.switchToKeyset(toKeyset); |
| 2592 return true; |
| 2593 } |
| 2594 } |
| 2595 else if (goog.array.contains(util.KEYSETS_SWITCH_WITH_US, |
| 2596 this.currentKeyset_)) { |
| 2597 toKeyset = this.currentKeyset_ + '.us'; |
| 2598 this.switchToKeyset(toKeyset); |
| 2599 return true; |
| 2600 } |
| 2601 return false; |
| 2602 }; |
| 2603 |
2422 }); // goog.scope | 2604 }); // goog.scope |
OLD | NEW |