Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: third_party/google_input_tools/src/chrome/os/inputview/controller.js

Issue 1576613002: Update Google Input Tools. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add missing APIs, remove bade dependencies. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698