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.array'); | 17 goog.require('goog.array'); |
18 goog.require('goog.async.Delay'); | 18 goog.require('goog.async.Delay'); |
19 goog.require('goog.dom'); | 19 goog.require('goog.dom'); |
20 goog.require('goog.dom.classlist'); | 20 goog.require('goog.dom.classlist'); |
21 goog.require('goog.events.EventHandler'); | 21 goog.require('goog.events.EventHandler'); |
22 goog.require('goog.events.EventType'); | 22 goog.require('goog.events.EventType'); |
23 goog.require('goog.i18n.bidi'); | 23 goog.require('goog.i18n.bidi'); |
24 goog.require('goog.object'); | 24 goog.require('goog.object'); |
25 goog.require('i18n.input.chrome.DataSource'); | 25 goog.require('i18n.input.chrome.DataSource'); |
| 26 goog.require('i18n.input.chrome.Statistics'); |
26 goog.require('i18n.input.chrome.inputview.Adapter'); | 27 goog.require('i18n.input.chrome.inputview.Adapter'); |
27 goog.require('i18n.input.chrome.inputview.CandidatesInfo'); | 28 goog.require('i18n.input.chrome.inputview.CandidatesInfo'); |
28 goog.require('i18n.input.chrome.inputview.ConditionName'); | 29 goog.require('i18n.input.chrome.inputview.ConditionName'); |
29 goog.require('i18n.input.chrome.inputview.Css'); | 30 goog.require('i18n.input.chrome.inputview.Css'); |
30 goog.require('i18n.input.chrome.inputview.KeyboardContainer'); | 31 goog.require('i18n.input.chrome.inputview.KeyboardContainer'); |
31 goog.require('i18n.input.chrome.inputview.M17nModel'); | 32 goog.require('i18n.input.chrome.inputview.M17nModel'); |
32 goog.require('i18n.input.chrome.inputview.Model'); | 33 goog.require('i18n.input.chrome.inputview.Model'); |
33 goog.require('i18n.input.chrome.inputview.PerfTracker'); | 34 goog.require('i18n.input.chrome.inputview.PerfTracker'); |
34 goog.require('i18n.input.chrome.inputview.ReadyState'); | 35 goog.require('i18n.input.chrome.inputview.ReadyState'); |
35 goog.require('i18n.input.chrome.inputview.Settings'); | 36 goog.require('i18n.input.chrome.inputview.Settings'); |
36 goog.require('i18n.input.chrome.inputview.SizeSpec'); | 37 goog.require('i18n.input.chrome.inputview.SizeSpec'); |
37 goog.require('i18n.input.chrome.inputview.SoundController'); | 38 goog.require('i18n.input.chrome.inputview.SoundController'); |
38 goog.require('i18n.input.chrome.inputview.SpecNodeName'); | 39 goog.require('i18n.input.chrome.inputview.SpecNodeName'); |
39 goog.require('i18n.input.chrome.inputview.StateType'); | 40 goog.require('i18n.input.chrome.inputview.StateType'); |
40 goog.require('i18n.input.chrome.inputview.Statistics'); | |
41 goog.require('i18n.input.chrome.inputview.SwipeDirection'); | 41 goog.require('i18n.input.chrome.inputview.SwipeDirection'); |
42 goog.require('i18n.input.chrome.inputview.elements.ElementType'); | 42 goog.require('i18n.input.chrome.inputview.elements.ElementType'); |
43 goog.require('i18n.input.chrome.inputview.elements.content.Candidate'); | 43 goog.require('i18n.input.chrome.inputview.elements.content.Candidate'); |
44 goog.require('i18n.input.chrome.inputview.elements.content.CandidateView'); | 44 goog.require('i18n.input.chrome.inputview.elements.content.CandidateView'); |
45 goog.require('i18n.input.chrome.inputview.elements.content.ExpandedCandidateView
'); | 45 goog.require('i18n.input.chrome.inputview.elements.content.ExpandedCandidateView
'); |
46 goog.require('i18n.input.chrome.inputview.elements.content.MenuView'); | 46 goog.require('i18n.input.chrome.inputview.elements.content.MenuView'); |
47 goog.require('i18n.input.chrome.inputview.events.EventType'); | 47 goog.require('i18n.input.chrome.inputview.events.EventType'); |
48 goog.require('i18n.input.chrome.inputview.events.KeyCodes'); | 48 goog.require('i18n.input.chrome.inputview.events.KeyCodes'); |
49 goog.require('i18n.input.chrome.inputview.handler.PointerHandler'); | 49 goog.require('i18n.input.chrome.inputview.handler.PointerHandler'); |
50 goog.require('i18n.input.chrome.inputview.util'); | 50 goog.require('i18n.input.chrome.inputview.util'); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 passwordLayout, name) { | 95 passwordLayout, name) { |
96 /** | 96 /** |
97 * The model. | 97 * The model. |
98 * | 98 * |
99 * @type {!i18n.input.chrome.inputview.Model} | 99 * @type {!i18n.input.chrome.inputview.Model} |
100 * @private | 100 * @private |
101 */ | 101 */ |
102 this.model_ = new i18n.input.chrome.inputview.Model(); | 102 this.model_ = new i18n.input.chrome.inputview.Model(); |
103 | 103 |
104 /** @private {!i18n.input.chrome.inputview.PerfTracker} */ | 104 /** @private {!i18n.input.chrome.inputview.PerfTracker} */ |
105 this.perfTracker_ = new i18n.input.chrome.inputview.PerfTracker(); | 105 this.perfTracker_ = new i18n.input.chrome.inputview.PerfTracker( |
| 106 PerfTracker.TickName.HTML_LOADED); |
106 | 107 |
107 /** | 108 /** |
108 * The layout map. | 109 * The layout map. |
109 * | 110 * |
110 * @type {!Object.<string, !Object>} | 111 * @type {!Object.<string, !Object>} |
111 * @private | 112 * @private |
112 */ | 113 */ |
113 this.layoutDataMap_ = {}; | 114 this.layoutDataMap_ = {}; |
114 | 115 |
115 /** | 116 /** |
(...skipping 25 matching lines...) Expand all Loading... |
141 * | 142 * |
142 * @type {!i18n.input.chrome.inputview.handler.PointerHandler} | 143 * @type {!i18n.input.chrome.inputview.handler.PointerHandler} |
143 * @private | 144 * @private |
144 */ | 145 */ |
145 this.pointerHandler_ = new i18n.input.chrome.inputview.handler. | 146 this.pointerHandler_ = new i18n.input.chrome.inputview.handler. |
146 PointerHandler(); | 147 PointerHandler(); |
147 | 148 |
148 /** | 149 /** |
149 * The statistics object for recording metrics values. | 150 * The statistics object for recording metrics values. |
150 * | 151 * |
151 * @type {!i18n.input.chrome.inputview.Statistics} | 152 * @type {!i18n.input.chrome.Statistics} |
152 * @private | 153 * @private |
153 */ | 154 */ |
154 this.statistics_ = i18n.input.chrome.inputview.Statistics.getInstance(); | 155 this.statistics_ = i18n.input.chrome.Statistics.getInstance(); |
155 | 156 |
156 /** @private {!i18n.input.chrome.inputview.ReadyState} */ | 157 /** @private {!i18n.input.chrome.inputview.ReadyState} */ |
157 this.readyState_ = new i18n.input.chrome.inputview.ReadyState(); | 158 this.readyState_ = new i18n.input.chrome.inputview.ReadyState(); |
158 | 159 |
159 /** @private {!i18n.input.chrome.inputview.Adapter} */ | 160 /** @private {!i18n.input.chrome.inputview.Adapter} */ |
160 this.adapter_ = new i18n.input.chrome.inputview.Adapter(this.readyState_); | 161 this.adapter_ = new i18n.input.chrome.inputview.Adapter(this.readyState_); |
161 | 162 |
162 /** @private {!i18n.input.chrome.inputview.KeyboardContainer} */ | 163 /** @private {!i18n.input.chrome.inputview.KeyboardContainer} */ |
163 this.container_ = new i18n.input.chrome.inputview.KeyboardContainer( | 164 this.container_ = new i18n.input.chrome.inputview.KeyboardContainer( |
164 this.adapter_); | 165 this.adapter_); |
165 this.container_.render(); | 166 this.container_.render(); |
166 | 167 |
167 /** @private {!i18n.input.chrome.inputview.SoundController} */ | 168 /** @private {!i18n.input.chrome.inputview.SoundController} */ |
168 this.soundController_ = new SoundController(false); | 169 this.soundController_ = new SoundController(false); |
169 | 170 |
170 /** | 171 /** |
171 * The context type and keyset mapping group by input method id. | 172 * The context type and keyset mapping group by input method id. |
172 * key: input method id. | 173 * key: input method id. |
173 * value: Object | 174 * value: Object |
174 * key: context type string. | 175 * key: context type string. |
175 * value: keyset string. | 176 * value: keyset string. |
176 * | 177 * |
177 * @private {!Object.<string, !Object.<string, string>>} | 178 * @private {!Object.<string, !Object.<string, string>>} |
178 */ | 179 */ |
179 this.contextTypeToKeysetMap_ = {}; | 180 this.contextTypeToKeysetMap_ = {}; |
180 | 181 |
| 182 /** |
| 183 * The stats map for input view closing. |
| 184 * |
| 185 * @type {!Object.<string, !Array.<number>>} |
| 186 * @private |
| 187 */ |
| 188 this.statsForClosing_ = {}; |
| 189 |
| 190 /** |
| 191 * The last height sent to window.resizeTo to avoid multiple equivalent calls. |
| 192 * |
| 193 * @private {number} |
| 194 */ |
| 195 this.lastResizeHeight_ = -1; |
| 196 |
| 197 /** |
| 198 * The activate (show) time stamp for statistics. |
| 199 * |
| 200 * @type {Date} |
| 201 * @private |
| 202 */ |
| 203 this.showTimeStamp_ = new Date(); |
| 204 |
181 this.initialize(keyset, languageCode, passwordLayout, name); | 205 this.initialize(keyset, languageCode, passwordLayout, name); |
182 /** | 206 /** |
183 * The suggestions. | 207 * The suggestions. |
184 * Note: sets a default empty result to avoid null check. | 208 * Note: sets a default empty result to avoid null check. |
185 * | 209 * |
186 * @private {!i18n.input.chrome.inputview.CandidatesInfo} | 210 * @private {!i18n.input.chrome.inputview.CandidatesInfo} |
187 */ | 211 */ |
188 this.candidatesInfo_ = i18n.input.chrome.inputview.CandidatesInfo.getEmpty(); | 212 this.candidatesInfo_ = i18n.input.chrome.inputview.CandidatesInfo.getEmpty(); |
189 | 213 |
190 this.registerEventHandler_(); | 214 this.registerEventHandler_(); |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 var settings = this.model_.settings; | 453 var settings = this.model_.settings; |
430 if (goog.isDef(e.msg['autoSpace'])) { | 454 if (goog.isDef(e.msg['autoSpace'])) { |
431 settings.autoSpace = e.msg['autoSpace']; | 455 settings.autoSpace = e.msg['autoSpace']; |
432 } | 456 } |
433 if (goog.isDef(e.msg['autoCapital'])) { | 457 if (goog.isDef(e.msg['autoCapital'])) { |
434 settings.autoCapital = e.msg['autoCapital']; | 458 settings.autoCapital = e.msg['autoCapital']; |
435 } | 459 } |
436 if (goog.isDef(e.msg['candidatesNavigation'])) { | 460 if (goog.isDef(e.msg['candidatesNavigation'])) { |
437 settings.candidatesNavigation = e.msg['candidatesNavigation']; | 461 settings.candidatesNavigation = e.msg['candidatesNavigation']; |
438 } | 462 } |
439 if (goog.isDef(e.msg['supportCompact'])) { | |
440 settings.supportCompact = e.msg['supportCompact']; | |
441 } | |
442 if (goog.isDef(e.msg[Name.KEYSET])) { | 463 if (goog.isDef(e.msg[Name.KEYSET])) { |
443 this.contextTypeToKeysetMap_[this.currentInputMethod_][ | 464 this.contextTypeToKeysetMap_[this.currentInputMethod_][ |
444 ContextType.DEFAULT] = e.msg[Name.KEYSET]; | 465 ContextType.DEFAULT] = e.msg[Name.KEYSET]; |
445 } | 466 } |
446 if (goog.isDef(e.msg['enableLongPress'])) { | 467 if (goog.isDef(e.msg['enableLongPress'])) { |
447 settings.enableLongPress = e.msg['enableLongPress']; | 468 settings.enableLongPress = e.msg['enableLongPress']; |
448 } | 469 } |
449 if (goog.isDef(e.msg['doubleSpacePeriod'])) { | 470 if (goog.isDef(e.msg['doubleSpacePeriod'])) { |
450 settings.doubleSpacePeriod = e.msg['doubleSpacePeriod']; | 471 settings.doubleSpacePeriod = e.msg['doubleSpacePeriod']; |
451 } | 472 } |
452 if (goog.isDef(e.msg['soundOnKeypress'])) { | 473 if (goog.isDef(e.msg['soundOnKeypress'])) { |
453 settings.soundOnKeypress = e.msg['soundOnKeypress']; | 474 settings.soundOnKeypress = e.msg['soundOnKeypress']; |
454 this.soundController_.setEnabled(settings.soundOnKeypress); | 475 this.soundController_.setEnabled(settings.soundOnKeypress); |
455 } | 476 } |
456 this.perfTracker_.tick(PerfTracker.TickName.BACKGROUND_SETTINGS_FETCHED); | 477 this.perfTracker_.tick(PerfTracker.TickName.BACKGROUND_SETTINGS_FETCHED); |
| 478 this.model_.stateManager.contextType = this.adapter_.getContextType(); |
457 var isPassword = this.adapter_.isPasswordBox(); | 479 var isPassword = this.adapter_.isPasswordBox(); |
458 this.switchToKeySet(this.getActiveKeyset_()); | 480 this.switchToKeySet(this.getActiveKeyset_()); |
459 }; | 481 }; |
460 | 482 |
461 | 483 |
462 /** | 484 /** |
463 * Callback for setting ready. | 485 * Callback for setting ready. |
464 * | 486 * |
465 * @private | 487 * @private |
466 */ | 488 */ |
467 Controller.prototype.onSettingsReady_ = function() { | 489 Controller.prototype.onSettingsReady_ = function() { |
468 if (this.isSettingReady) { | 490 if (this.isSettingReady) { |
469 return; | 491 return; |
470 } | 492 } |
471 | 493 |
472 this.isSettingReady = true; | 494 this.isSettingReady = true; |
473 var keysetMap = this.contextTypeToKeysetMap_[this.currentInputMethod_]; | 495 var keysetMap = this.contextTypeToKeysetMap_[this.currentInputMethod_]; |
474 if (this.adapter_.isA11yMode) { | 496 if (this.adapter_.isA11yMode) { |
475 keysetMap[ContextType.PASSWORD] = keysetMap[ContextType.DEFAULT] = | 497 keysetMap[ContextType.PASSWORD] = keysetMap[ContextType.DEFAULT] = |
476 util.getConfigName(keysetMap[ContextType.DEFAULT]); | 498 util.getConfigName(keysetMap[ContextType.DEFAULT]); |
477 } else { | 499 } else { |
478 var preferredKeyset = /** @type {string} */ (this.model_.settings. | 500 var preferredKeyset = /** @type {string} */ (this.model_.settings. |
479 getPreference(util.getConfigName( | 501 getPreference(util.getConfigName( |
480 keysetMap[ContextType.DEFAULT]))); | 502 keysetMap[ContextType.DEFAULT]))); |
481 if (preferredKeyset) { | 503 if (preferredKeyset) { |
482 keysetMap[ContextType.PASSWORD] = keysetMap[ContextType.DEFAULT] = | 504 keysetMap[ContextType.PASSWORD] = keysetMap[ContextType.DEFAULT] = |
483 preferredKeyset; | 505 preferredKeyset; |
484 } | 506 } |
485 } | 507 } |
| 508 if (!this.adapter_.isExperimental && keysetMap[ContextType.DEFAULT] == |
| 509 'zhuyin.compact.qwerty') { |
| 510 keysetMap[ContextType.DEFAULT] = 'zhuyin'; |
| 511 } |
486 this.maybeCreateViews_(); | 512 this.maybeCreateViews_(); |
487 this.switchToKeySet(this.getActiveKeyset_()); | 513 this.switchToKeySet(this.getActiveKeyset_()); |
488 }; | 514 }; |
489 | 515 |
490 | 516 |
491 /** | 517 /** |
492 * Gets the data for spatial module. | 518 * Gets the data for spatial module. |
493 * | 519 * |
494 * @param {!content.SoftKey} key . | 520 * @param {!content.SoftKey} key . |
495 * @param {number} x The x-offset of the touch point. | 521 * @param {number} x The x-offset of the touch point. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
551 * | 577 * |
552 * @param {!i18n.input.chrome.inputview.events.PointerEvent} e . | 578 * @param {!i18n.input.chrome.inputview.events.PointerEvent} e . |
553 * @private | 579 * @private |
554 */ | 580 */ |
555 Controller.prototype.onPointerEvent_ = function(e) { | 581 Controller.prototype.onPointerEvent_ = function(e) { |
556 if ((this.adapter_.isChromeVoxOn || !this.model_.settings.enableLongPress) && | 582 if ((this.adapter_.isChromeVoxOn || !this.model_.settings.enableLongPress) && |
557 e.type == EventType.LONG_PRESS) { | 583 e.type == EventType.LONG_PRESS) { |
558 return; | 584 return; |
559 } | 585 } |
560 | 586 |
| 587 if (e.type == EventType.POINTER_UP) { |
| 588 this.stopBackspaceAutoRepeat_(); |
| 589 } |
| 590 |
561 if (e.view) { | 591 if (e.view) { |
562 this.handlePointerAction_(e.view, e); | 592 this.handlePointerAction_(e.view, e); |
563 } else { | 593 } else { |
564 var tabbableKeysets = [ | 594 var tabbableKeysets = [ |
565 Controller.HANDWRITING_VIEW_CODE_, | 595 Controller.HANDWRITING_VIEW_CODE_, |
566 Controller.EMOJI_VIEW_CODE_]; | 596 Controller.EMOJI_VIEW_CODE_]; |
567 if (goog.array.contains(tabbableKeysets, this.currentKeyset_)) { | 597 if (goog.array.contains(tabbableKeysets, this.currentKeyset_)) { |
568 this.resetAll_(); | 598 this.resetAll_(); |
569 this.switchToKeySet(this.container_.currentKeysetView.fromKeyset); | 599 this.switchToKeySet(this.container_.currentKeysetView.fromKeyset); |
570 } | 600 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
623 case CommandEnum.SWITCH_IME: | 653 case CommandEnum.SWITCH_IME: |
624 var inputMethodId = opt_arg; | 654 var inputMethodId = opt_arg; |
625 if (inputMethodId) { | 655 if (inputMethodId) { |
626 this.adapter_.switchToInputMethod(inputMethodId); | 656 this.adapter_.switchToInputMethod(inputMethodId); |
627 } | 657 } |
628 break; | 658 break; |
629 | 659 |
630 case CommandEnum.SWITCH_KEYSET: | 660 case CommandEnum.SWITCH_KEYSET: |
631 var keyset = opt_arg; | 661 var keyset = opt_arg; |
632 if (keyset) { | 662 if (keyset) { |
633 this.statistics_.recordSwitch(keyset); | 663 this.recordStatsForClosing_( |
| 664 'InputMethod.VirtualKeyboard.LayoutSwitch', 1, 25, 25); |
634 this.switchToKeySet(keyset); | 665 this.switchToKeySet(keyset); |
635 } | 666 } |
636 break; | 667 break; |
637 case CommandEnum.OPEN_EMOJI: | 668 case CommandEnum.OPEN_EMOJI: |
638 this.switchToKeySet(Controller.EMOJI_VIEW_CODE_); | 669 this.switchToKeySet(Controller.EMOJI_VIEW_CODE_); |
639 break; | 670 break; |
640 | 671 |
641 case CommandEnum.OPEN_HANDWRITING: | 672 case CommandEnum.OPEN_HANDWRITING: |
642 // TODO: remember handwriting keyset. | 673 // TODO: remember handwriting keyset. |
643 this.switchToKeySet(Controller.HANDWRITING_VIEW_CODE_); | 674 this.switchToKeySet(Controller.HANDWRITING_VIEW_CODE_); |
(...skipping 15 matching lines...) Expand all Loading... |
659 * @param {!i18n.input.chrome.inputview.events.PointerEvent} e . | 690 * @param {!i18n.input.chrome.inputview.events.PointerEvent} e . |
660 * @private | 691 * @private |
661 */ | 692 */ |
662 Controller.prototype.handlePointerAction_ = function(view, e) { | 693 Controller.prototype.handlePointerAction_ = function(view, e) { |
663 if (e.type == i18n.input.chrome.inputview.events.EventType.SWIPE) { | 694 if (e.type == i18n.input.chrome.inputview.events.EventType.SWIPE) { |
664 e = /** @type {!i18n.input.chrome.inputview.events.SwipeEvent} */ (e); | 695 e = /** @type {!i18n.input.chrome.inputview.events.SwipeEvent} */ (e); |
665 this.handleSwipeAction_(view, e); | 696 this.handleSwipeAction_(view, e); |
666 } | 697 } |
667 switch (view.type) { | 698 switch (view.type) { |
668 case ElementType.BACK_BUTTON: | 699 case ElementType.BACK_BUTTON: |
| 700 if (e.type == EventType.POINTER_OUT || e.type == EventType.POINTER_UP) { |
| 701 view.setHighlighted(false); |
| 702 } else if (e.type == EventType.POINTER_DOWN || |
| 703 e.type == EventType.POINTER_OVER) { |
| 704 view.setHighlighted(true); |
| 705 } |
669 if (e.type == EventType.POINTER_UP) { | 706 if (e.type == EventType.POINTER_UP) { |
670 this.switchToKeySet(this.container_.currentKeysetView.fromKeyset); | 707 this.switchToKeySet(this.container_.currentKeysetView.fromKeyset); |
| 708 this.clearCandidates_(); |
671 } | 709 } |
672 return; | 710 return; |
673 case ElementType.EXPAND_CANDIDATES: | 711 case ElementType.EXPAND_CANDIDATES: |
674 if (e.type == EventType.POINTER_UP) { | 712 if (e.type == EventType.POINTER_UP) { |
675 this.showCandidates_(this.candidatesInfo_.source, | 713 this.showCandidates_(this.candidatesInfo_.source, |
676 this.candidatesInfo_.candidates, | 714 this.candidatesInfo_.candidates, |
677 Controller.CandidatesOperation.EXPAND); | 715 Controller.CandidatesOperation.EXPAND); |
678 } | 716 } |
679 return; | 717 return; |
680 case ElementType.SHRINK_CANDIDATES: | 718 case ElementType.SHRINK_CANDIDATES: |
681 if (e.type == EventType.POINTER_UP) { | 719 if (e.type == EventType.POINTER_UP) { |
682 this.showCandidates_(this.candidatesInfo_.source, | 720 this.showCandidates_(this.candidatesInfo_.source, |
683 this.candidatesInfo_.candidates, | 721 this.candidatesInfo_.candidates, |
684 Controller.CandidatesOperation.SHRINK); | 722 Controller.CandidatesOperation.SHRINK); |
685 } | 723 } |
686 return; | 724 return; |
687 case ElementType.CANDIDATE: | 725 case ElementType.CANDIDATE: |
688 view = /** @type {!Candidate} */ (view); | 726 view = /** @type {!Candidate} */ (view); |
689 if (e.type == EventType.POINTER_UP) { | 727 if (e.type == EventType.POINTER_UP) { |
690 if (view.candidateType == CandidateType.CANDIDATE) { | 728 if (view.candidateType == CandidateType.CANDIDATE) { |
691 this.adapter_.selectCandidate(view.candidate); | 729 this.adapter_.selectCandidate(view.candidate); |
692 } else if (view.candidateType == CandidateType.NUMBER) { | 730 } else if (view.candidateType == CandidateType.NUMBER) { |
693 this.adapter_.commitText(view.candidate[Name.CANDIDATE]); | 731 this.adapter_.commitText(view.candidate[Name.CANDIDATE]); |
694 } | 732 } |
695 this.container_.cleanStroke(); | 733 this.container_.cleanStroke(); |
| 734 this.soundController_.onKeyUp(ElementType.CANDIDATE); |
696 } | 735 } |
697 if (e.type == EventType.POINTER_OUT || e.type == EventType.POINTER_UP) { | 736 if (e.type == EventType.POINTER_OUT || e.type == EventType.POINTER_UP) { |
698 view.setHighlighted(false); | 737 view.setHighlighted(false); |
699 } else if (e.type == EventType.POINTER_DOWN || | 738 } else if (e.type == EventType.POINTER_DOWN || |
700 e.type == EventType.POINTER_OVER) { | 739 e.type == EventType.POINTER_OVER) { |
701 view.setHighlighted(true); | 740 view.setHighlighted(true); |
702 } | 741 } |
703 return; | 742 return; |
704 | 743 |
705 case ElementType.ALTDATA_VIEW: | 744 case ElementType.ALTDATA_VIEW: |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
797 break; | 836 break; |
798 case ElementType.CANDIDATES_PAGE_DOWN: | 837 case ElementType.CANDIDATES_PAGE_DOWN: |
799 if (e.type == EventType.POINTER_UP) { | 838 if (e.type == EventType.POINTER_UP) { |
800 this.container_.expandedCandidateView.pageDown(); | 839 this.container_.expandedCandidateView.pageDown(); |
801 } | 840 } |
802 break; | 841 break; |
803 case ElementType.CHARACTER_KEY: | 842 case ElementType.CHARACTER_KEY: |
804 key = /** @type {!content.CharacterKey} */ (softKey); | 843 key = /** @type {!content.CharacterKey} */ (softKey); |
805 if (e.type == EventType.LONG_PRESS) { | 844 if (e.type == EventType.LONG_PRESS) { |
806 this.container_.altDataView.show( | 845 this.container_.altDataView.show( |
807 key, goog.i18n.bidi.isRtlLanguage(this.languageCode_)); | 846 key, goog.i18n.bidi.isRtlLanguage(this.languageCode_), |
| 847 this.adapter_.isExperimental); |
808 } else if (e.type == EventType.POINTER_UP) { | 848 } else if (e.type == EventType.POINTER_UP) { |
809 this.model_.stateManager.triggerChording(); | 849 this.model_.stateManager.triggerChording(); |
810 var ch = key.getActiveCharacter(); | 850 var ch = key.getActiveCharacter(); |
811 this.adapter_.sendKeyDownAndUpEvent(ch, key.id, key.keyCode, | 851 this.adapter_.sendKeyDownAndUpEvent(ch, key.id, key.keyCode, |
812 this.getSpatialData_(key, e.x, e.y)); | 852 this.getSpatialData_(key, e.x, e.y)); |
813 this.clearUnstickyState_(); | 853 this.clearUnstickyState_(); |
814 key.flickerredCharacter = ''; | 854 key.flickerredCharacter = ''; |
815 } | 855 } |
816 break; | 856 break; |
817 | 857 |
818 case ElementType.MODIFIER_KEY: | 858 case ElementType.MODIFIER_KEY: |
819 key = /** @type {!content.ModifierKey} */ (softKey); | 859 key = /** @type {!content.ModifierKey} */ (softKey); |
820 var isStateEnabled = this.model_.stateManager.hasState(key.toState); | 860 var isStateEnabled = this.model_.stateManager.hasState(key.toState); |
821 var isChording = this.model_.stateManager.isChording(key.toState); | 861 var isChording = this.model_.stateManager.isChording(key.toState); |
822 if (e.type == EventType.POINTER_DOWN) { | 862 if (e.type == EventType.POINTER_DOWN) { |
823 this.changeState_(key.toState, !isStateEnabled, true); | 863 this.changeState_(key.toState, !isStateEnabled, true, false); |
824 this.model_.stateManager.setKeyDown(key.toState, true); | 864 this.model_.stateManager.setKeyDown(key.toState, true); |
825 } else if (e.type == EventType.POINTER_UP || e.type == EventType. | 865 } else if (e.type == EventType.POINTER_UP || e.type == EventType. |
826 POINTER_OUT) { | 866 POINTER_OUT) { |
827 if (isChording) { | 867 if (isChording) { |
828 this.changeState_(key.toState, false, false); | 868 this.changeState_(key.toState, false, false); |
829 } else if (key.toState != StateType.CAPSLOCK && | 869 } else if (key.toState == StateType.CAPSLOCK) { |
830 this.model_.stateManager.isKeyDown(key.toState)) { | 870 this.changeState_(key.toState, isStateEnabled, true, true); |
| 871 } else if (this.model_.stateManager.isKeyDown(key.toState)) { |
831 this.changeState_(key.toState, isStateEnabled, false); | 872 this.changeState_(key.toState, isStateEnabled, false); |
832 } | 873 } |
833 this.model_.stateManager.setKeyDown(key.toState, false); | 874 this.model_.stateManager.setKeyDown(key.toState, false); |
834 } else if (e.type == EventType.DOUBLE_CLICK) { | 875 } else if (e.type == EventType.DOUBLE_CLICK) { |
835 this.changeState_(key.toState, isStateEnabled, true); | 876 this.changeState_(key.toState, isStateEnabled, true, true); |
836 } else if (e.type == EventType.LONG_PRESS) { | 877 } else if (e.type == EventType.LONG_PRESS) { |
837 if (!isChording) { | 878 if (!isChording) { |
838 this.changeState_(key.toState, true, true); | 879 this.changeState_(key.toState, true, true, true); |
839 this.model_.stateManager.setKeyDown(key.toState, false); | 880 this.model_.stateManager.setKeyDown(key.toState, false); |
840 } | 881 } |
841 } | 882 } |
842 break; | 883 break; |
843 | 884 |
844 case ElementType.BACKSPACE_KEY: | 885 case ElementType.BACKSPACE_KEY: |
845 key = /** @type {!content.FunctionalKey} */ (softKey); | 886 key = /** @type {!content.FunctionalKey} */ (softKey); |
846 if (e.type == EventType.POINTER_DOWN) { | 887 if (e.type == EventType.POINTER_DOWN) { |
847 this.backspaceTick_(); | 888 this.backspaceTick_(); |
848 } else if (e.type == EventType.POINTER_UP || e.type == EventType. | 889 } else if (e.type == EventType.POINTER_UP || e.type == EventType. |
849 POINTER_OUT) { | 890 POINTER_OUT) { |
850 this.stopBackspaceAutoRepeat_(); | 891 this.stopBackspaceAutoRepeat_(); |
851 this.adapter_.sendKeyUpEvent('\u0008', KeyCodes.BACKSPACE); | 892 this.adapter_.sendKeyUpEvent('\u0008', KeyCodes.BACKSPACE); |
852 } | 893 } |
853 break; | 894 break; |
854 | 895 |
855 case ElementType.TAB_KEY: | 896 case ElementType.TAB_KEY: |
856 key = /** @type {!content.FunctionalKey} */ (softKey); | 897 key = /** @type {!content.FunctionalKey} */ (softKey); |
857 if (e.type == EventType.POINTER_DOWN) { | 898 if (e.type == EventType.POINTER_DOWN) { |
858 this.adapter_.sendKeyDownEvent('\u0009', KeyCodes.TAB); | 899 this.adapter_.sendKeyDownEvent('\u0009', KeyCodes.TAB); |
859 } else if (e.type == EventType.POINTER_UP) { | 900 } else if (e.type == EventType.POINTER_UP) { |
860 this.adapter_.sendKeyUpEvent('\u0009', KeyCodes.TAB); | 901 this.adapter_.sendKeyUpEvent('\u0009', KeyCodes.TAB); |
861 } | 902 } |
862 break; | 903 break; |
863 | 904 |
864 case ElementType.ENTER_KEY: | 905 case ElementType.ENTER_KEY: |
865 key = /** @type {!content.FunctionalKey} */ (softKey); | 906 key = /** @type {!content.FunctionalKey} */ (softKey); |
866 if (e.type == EventType.POINTER_DOWN) { | 907 if (e.type == EventType.POINTER_UP) { |
867 this.adapter_.sendKeyDownEvent('\u000D', KeyCodes.ENTER); | 908 this.adapter_.sendKeyDownAndUpEvent('\u000D', KeyCodes.ENTER); |
868 } else if (e.type == EventType.POINTER_UP) { | |
869 this.adapter_.sendKeyUpEvent('\u000D', KeyCodes.ENTER); | |
870 } | 909 } |
871 break; | 910 break; |
872 | 911 |
873 case ElementType.ARROW_UP: | 912 case ElementType.ARROW_UP: |
874 if (e.type == EventType.POINTER_DOWN) { | 913 if (e.type == EventType.POINTER_DOWN) { |
875 this.adapter_.sendKeyDownEvent('', KeyCodes.ARROW_UP); | 914 this.adapter_.sendKeyDownEvent('', KeyCodes.ARROW_UP); |
876 } else if (e.type == EventType.POINTER_UP) { | 915 } else if (e.type == EventType.POINTER_UP) { |
877 this.adapter_.sendKeyUpEvent('', KeyCodes.ARROW_UP); | 916 this.adapter_.sendKeyUpEvent('', KeyCodes.ARROW_UP); |
878 } | 917 } |
879 break; | 918 break; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
918 KeyCodes.SPACE); | 957 KeyCodes.SPACE); |
919 this.clearUnstickyState_(); | 958 this.clearUnstickyState_(); |
920 } else if (e.type == EventType.DOUBLE_CLICK && doubleSpacePeriod) { | 959 } else if (e.type == EventType.DOUBLE_CLICK && doubleSpacePeriod) { |
921 this.adapter_.doubleClickOnSpaceKey(); | 960 this.adapter_.doubleClickOnSpaceKey(); |
922 } | 961 } |
923 break; | 962 break; |
924 | 963 |
925 case ElementType.SWITCHER_KEY: | 964 case ElementType.SWITCHER_KEY: |
926 key = /** @type {!content.SwitcherKey} */ (softKey); | 965 key = /** @type {!content.SwitcherKey} */ (softKey); |
927 if (e.type == EventType.POINTER_UP) { | 966 if (e.type == EventType.POINTER_UP) { |
928 this.statistics_.recordSwitch(key.toKeyset); | 967 this.recordStatsForClosing_( |
| 968 'InputMethod.VirtualKeyboard.LayoutSwitch', 1, 25, 25); |
929 if (this.isSubKeyset_(key.toKeyset, this.currentKeyset_)) { | 969 if (this.isSubKeyset_(key.toKeyset, this.currentKeyset_)) { |
930 this.model_.stateManager.reset(); | 970 this.model_.stateManager.reset(); |
931 this.container_.update(); | 971 this.container_.update(); |
932 this.updateContextModifierState_(); | 972 this.updateContextModifierState_(); |
933 this.container_.menuView.hide(); | 973 this.container_.menuView.hide(); |
934 } else { | 974 } else { |
935 this.resetAll_(); | 975 this.resetAll_(); |
936 } | 976 } |
937 // Switch to the specific keyboard. | 977 // Switch to the specific keyboard. |
938 this.switchToKeySet(key.toKeyset); | 978 this.switchToKeySet(key.toKeyset); |
939 if (key.record) { | 979 if (key.record) { |
940 this.model_.settings.savePreference( | 980 this.model_.settings.savePreference( |
941 util.getConfigName(key.toKeyset), | 981 util.getConfigName(key.toKeyset), |
942 key.toKeyset); | 982 key.toKeyset); |
943 } | 983 } |
944 } | 984 } |
945 break; | 985 break; |
946 | 986 |
947 case ElementType.COMPACT_KEY: | 987 case ElementType.COMPACT_KEY: |
948 key = /** @type {!content.CompactKey} */ (softKey); | 988 key = /** @type {!content.CompactKey} */ (softKey); |
949 if (e.type == EventType.LONG_PRESS) { | 989 if (e.type == EventType.LONG_PRESS) { |
950 this.container_.altDataView.show( | 990 this.container_.altDataView.show( |
951 key, goog.i18n.bidi.isRtlLanguage(this.languageCode_)); | 991 key, goog.i18n.bidi.isRtlLanguage(this.languageCode_), |
| 992 this.adapter_.isExperimental); |
952 } else if (e.type == EventType.POINTER_UP) { | 993 } else if (e.type == EventType.POINTER_UP) { |
953 this.model_.stateManager.triggerChording(); | 994 this.model_.stateManager.triggerChording(); |
954 this.adapter_.sendKeyDownAndUpEvent(key.getActiveCharacter(), '', 0, | 995 this.adapter_.sendKeyDownAndUpEvent(key.getActiveCharacter(), '', 0, |
955 this.getSpatialData_(key, e.x, e.y)); | 996 this.getSpatialData_(key, e.x, e.y)); |
956 this.clearUnstickyState_(); | 997 this.clearUnstickyState_(); |
957 key.flickerredCharacter = ''; | 998 key.flickerredCharacter = ''; |
958 } | 999 } |
959 break; | 1000 break; |
960 | 1001 |
961 case ElementType.HIDE_KEYBOARD_KEY: | 1002 case ElementType.HIDE_KEYBOARD_KEY: |
| 1003 var defaultKeyset = this.getActiveKeyset_(); |
962 if (e.type == EventType.POINTER_UP) { | 1004 if (e.type == EventType.POINTER_UP) { |
963 this.adapter_.hideKeyboard(); | 1005 this.adapter_.hideKeyboard(); |
964 } | 1006 } |
| 1007 if (this.currentKeyset_ != defaultKeyset) { |
| 1008 this.switchToKeySet(defaultKeyset); |
| 1009 } |
965 break; | 1010 break; |
966 | 1011 |
967 case ElementType.MENU_KEY: | 1012 case ElementType.MENU_KEY: |
968 key = /** @type {!content.MenuKey} */ (softKey); | 1013 key = /** @type {!content.MenuKey} */ (softKey); |
969 if (e.type == EventType.POINTER_DOWN) { | 1014 if (e.type == EventType.POINTER_DOWN) { |
970 var isCompact = this.currentKeyset_.indexOf('compact') != -1; | 1015 var isCompact = this.currentKeyset_.indexOf('compact') != -1; |
971 var remappedKeyset = this.getRemappedKeyset_(this.currentKeyset_); | 1016 var defaultKeyset = this.contextTypeToKeysetMap_[ |
972 var keysetData = this.keysetDataMap_[remappedKeyset]; | 1017 this.currentInputMethod_][ContextType.DEFAULT]; |
973 var enableCompact = !this.adapter_.isA11yMode && | 1018 var enableCompact = !this.adapter_.isA11yMode && goog.array.contains( |
974 !!keysetData[SpecNodeName.HAS_COMPACT_KEYBOARD] && | 1019 util.KEYSETS_HAVE_COMPACT, defaultKeyset.split(/\./)[0]); |
975 this.model_.settings.supportCompact; | 1020 if (defaultKeyset == 'zhuyin' && !this.adapter_.isExperimental || |
| 1021 this.languageCode_ == 'ko') { |
| 1022 // Hides 'switch to compact' for zhuyin when not in experimental env. |
| 1023 enableCompact = false; |
| 1024 } |
976 var self = this; | 1025 var self = this; |
977 var currentKeyset = this.currentKeyset_; | |
978 var hasHwt = !this.adapter_.isPasswordBox() && | 1026 var hasHwt = !this.adapter_.isPasswordBox() && |
979 !Controller.DISABLE_HWT && goog.object.contains( | 1027 !Controller.DISABLE_HWT && goog.object.contains( |
980 InputToolCode, this.getHwtInputToolCode_()); | 1028 InputToolCode, this.getHwtInputToolCode_()) && |
| 1029 this.languageCode_ != 'ko'; |
981 var enableSettings = this.shouldEnableSettings() && | 1030 var enableSettings = this.shouldEnableSettings() && |
982 window.inputview && inputview.openSettings; | 1031 !!window.inputview && !!inputview.openSettings; |
983 this.adapter_.getInputMethods(function(inputMethods) { | 1032 this.adapter_.getInputMethods(function(inputMethods) { |
984 this.container_.menuView.show(key, currentKeyset, isCompact, | 1033 this.container_.menuView.show(key, defaultKeyset, isCompact, |
985 enableCompact, this.currentInputMethod_, inputMethods, hasHwt, | 1034 enableCompact, this.currentInputMethod_, inputMethods, hasHwt, |
986 enableSettings, this.adapter_.isExperimental); | 1035 enableSettings, this.adapter_.isExperimental); |
987 }.bind(this)); | 1036 }.bind(this)); |
988 } | 1037 } |
989 break; | 1038 break; |
990 | 1039 |
991 case ElementType.GLOBE_KEY: | 1040 case ElementType.GLOBE_KEY: |
992 if (e.type == EventType.POINTER_UP) { | 1041 if (e.type == EventType.POINTER_UP) { |
993 this.adapter_.clearModifierStates(); | 1042 this.adapter_.clearModifierStates(); |
994 this.adapter_.setModifierState( | 1043 this.adapter_.setModifierState( |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1027 this.container_.update(); | 1076 this.container_.update(); |
1028 }; | 1077 }; |
1029 | 1078 |
1030 | 1079 |
1031 /** | 1080 /** |
1032 * Stops the auto-repeat for backspace. | 1081 * Stops the auto-repeat for backspace. |
1033 * | 1082 * |
1034 * @private | 1083 * @private |
1035 */ | 1084 */ |
1036 Controller.prototype.stopBackspaceAutoRepeat_ = function() { | 1085 Controller.prototype.stopBackspaceAutoRepeat_ = function() { |
1037 goog.dispose(this.backspaceAutoRepeat_); | 1086 if (this.backspaceAutoRepeat_) { |
1038 this.backspaceAutoRepeat_ = null; | 1087 goog.dispose(this.backspaceAutoRepeat_); |
1039 this.adapter_.sendKeyUpEvent('\u0008', KeyCodes.BACKSPACE); | 1088 this.backspaceAutoRepeat_ = null; |
1040 this.backspaceRepeated_ = 0; | 1089 this.adapter_.sendKeyUpEvent('\u0008', KeyCodes.BACKSPACE); |
| 1090 this.backspaceRepeated_ = 0; |
| 1091 } |
1041 }; | 1092 }; |
1042 | 1093 |
1043 | 1094 |
1044 /** | 1095 /** |
1045 * The tick for the backspace key. | 1096 * The tick for the backspace key. |
1046 * | 1097 * |
1047 * @private | 1098 * @private |
1048 */ | 1099 */ |
1049 Controller.prototype.backspaceTick_ = function() { | 1100 Controller.prototype.backspaceTick_ = function() { |
1050 if (this.backspaceRepeated_ >= Controller.BACKSPACE_REPEAT_LIMIT_) { | 1101 if (this.backspaceRepeated_ >= Controller.BACKSPACE_REPEAT_LIMIT_) { |
(...skipping 14 matching lines...) Expand all Loading... |
1065 }; | 1116 }; |
1066 | 1117 |
1067 | 1118 |
1068 /** | 1119 /** |
1069 * Callback for VISIBILITY_CHANGE. | 1120 * Callback for VISIBILITY_CHANGE. |
1070 * | 1121 * |
1071 * @private | 1122 * @private |
1072 */ | 1123 */ |
1073 Controller.prototype.onVisibilityChange_ = function() { | 1124 Controller.prototype.onVisibilityChange_ = function() { |
1074 if (!this.adapter_.isVisible) { | 1125 if (!this.adapter_.isVisible) { |
| 1126 for (var name in this.statsForClosing_) { |
| 1127 var stat = this.statsForClosing_[name]; |
| 1128 this.statistics_.recordValue(name, stat[0], stat[1], stat[2]); |
| 1129 } |
| 1130 this.statistics_.recordValue('InputMethod.VirtualKeyboard.Duration', |
| 1131 Math.floor((new Date() - this.showTimeStamp_) / 1000), 4096, 50); |
| 1132 this.statsForClosing_ = {}; |
| 1133 this.showTimeStamp_ = new Date(); |
1075 this.resetAll_(); | 1134 this.resetAll_(); |
1076 } | 1135 } |
1077 }; | 1136 }; |
1078 | 1137 |
1079 | 1138 |
1080 /** | 1139 /** |
1081 * Resets the whole keyboard include clearing candidates, | 1140 * Resets the whole keyboard include clearing candidates, |
1082 * reset modifier state, etc. | 1141 * reset modifier state, etc. |
1083 * | 1142 * |
1084 * @private | 1143 * @private |
1085 */ | 1144 */ |
1086 Controller.prototype.resetAll_ = function() { | 1145 Controller.prototype.resetAll_ = function() { |
1087 this.clearCandidates_(); | 1146 this.clearCandidates_(); |
| 1147 this.container_.cleanStroke(); |
1088 this.container_.candidateView.hideNumberRow(); | 1148 this.container_.candidateView.hideNumberRow(); |
1089 this.model_.stateManager.reset(); | 1149 this.model_.stateManager.reset(); |
1090 this.container_.update(); | 1150 this.container_.update(); |
1091 this.updateContextModifierState_(); | 1151 this.updateContextModifierState_(); |
1092 this.deadKey_ = ''; | 1152 this.deadKey_ = ''; |
1093 this.resize(); | 1153 this.resize(); |
1094 this.container_.expandedCandidateView.close(); | 1154 this.container_.expandedCandidateView.close(); |
1095 this.container_.menuView.hide(); | 1155 this.container_.menuView.hide(); |
1096 }; | 1156 }; |
1097 | 1157 |
1098 | 1158 |
1099 /** | 1159 /** |
1100 * Callback when the context is changed. | 1160 * Callback when the context is changed. |
1101 * | 1161 * |
1102 * @private | 1162 * @private |
1103 */ | 1163 */ |
1104 Controller.prototype.onContextFocus_ = function() { | 1164 Controller.prototype.onContextFocus_ = function() { |
1105 this.resetAll_(); | 1165 this.resetAll_(); |
| 1166 this.model_.stateManager.contextType = this.adapter_.getContextType(); |
1106 this.switchToKeySet(this.getActiveKeyset_()); | 1167 this.switchToKeySet(this.getActiveKeyset_()); |
1107 }; | 1168 }; |
1108 | 1169 |
1109 | 1170 |
1110 /** | 1171 /** |
1111 * Callback when surrounding text is changed. | 1172 * Callback when surrounding text is changed. |
1112 * | 1173 * |
1113 * @param {!i18n.input.chrome.inputview.events.SurroundingTextChangedEvent} e . | 1174 * @param {!i18n.input.chrome.inputview.events.SurroundingTextChangedEvent} e . |
1114 * @private | 1175 * @private |
1115 */ | 1176 */ |
(...skipping 14 matching lines...) Expand all Loading... |
1130 }; | 1191 }; |
1131 | 1192 |
1132 | 1193 |
1133 /** | 1194 /** |
1134 * Callback for Context blurs. | 1195 * Callback for Context blurs. |
1135 * | 1196 * |
1136 * @private | 1197 * @private |
1137 */ | 1198 */ |
1138 Controller.prototype.onContextBlur_ = function() { | 1199 Controller.prototype.onContextBlur_ = function() { |
1139 this.clearCandidates_(); | 1200 this.clearCandidates_(); |
| 1201 this.container_.cleanStroke(); |
1140 this.deadKey_ = ''; | 1202 this.deadKey_ = ''; |
1141 this.container_.menuView.hide(); | 1203 this.container_.menuView.hide(); |
1142 }; | 1204 }; |
1143 | 1205 |
1144 | 1206 |
1145 /** | 1207 /** |
1146 * Backspace key is down. | 1208 * Backspace key is down. |
1147 * | 1209 * |
1148 * @private | 1210 * @private |
1149 */ | 1211 */ |
1150 Controller.prototype.backspaceDown_ = function() { | 1212 Controller.prototype.backspaceDown_ = function() { |
1151 if (this.container_.hasStrokesOnCanvas()) { | 1213 if (this.container_.hasStrokesOnCanvas()) { |
1152 this.clearCandidates_(); | 1214 this.clearCandidates_(); |
1153 this.container_.cleanStroke(); | 1215 this.container_.cleanStroke(); |
1154 } else { | 1216 } else { |
1155 this.adapter_.sendKeyDownEvent('\u0008', KeyCodes.BACKSPACE); | 1217 this.adapter_.sendKeyDownEvent('\u0008', KeyCodes.BACKSPACE); |
1156 } | 1218 } |
| 1219 this.recordStatsForClosing_( |
| 1220 'InputMethod.VirtualKeyboard.BackspaceCount', 1, 4095, 4096); |
| 1221 this.statistics_.recordEnum('InputMethod.VirtualKeyboard.BackspaceOnLayout', |
| 1222 this.statistics_.getLayoutType(this.currentKeyset_, |
| 1223 this.adapter_.isA11yMode), |
| 1224 i18n.input.chrome.Statistics.LayoutTypes.MAX); |
1157 }; | 1225 }; |
1158 | 1226 |
1159 | 1227 |
1160 /** | 1228 /** |
1161 * Callback for state change. | 1229 * Callback for state change. |
1162 * | 1230 * |
1163 * @param {StateType} stateType The state type. | 1231 * @param {StateType} stateType The state type. |
1164 * @param {boolean} enable True to enable the state. | 1232 * @param {boolean} enable True to enable the state. |
1165 * @param {boolean} isSticky True to make the state sticky. | 1233 * @param {boolean} isSticky True to make the state sticky. |
| 1234 * @param {boolean=} opt_isFinalSticky . |
1166 * @private | 1235 * @private |
1167 */ | 1236 */ |
1168 Controller.prototype.changeState_ = function(stateType, enable, isSticky) { | 1237 Controller.prototype.changeState_ = function(stateType, enable, isSticky, |
| 1238 opt_isFinalSticky) { |
1169 if (stateType == StateType.ALTGR) { | 1239 if (stateType == StateType.ALTGR) { |
1170 var code = KeyCodes.ALT_RIGHT; | 1240 var code = KeyCodes.ALT_RIGHT; |
1171 if (enable) { | 1241 if (enable) { |
1172 this.adapter_.sendKeyDownEvent('', code); | 1242 this.adapter_.sendKeyDownEvent('', code); |
1173 } else { | 1243 } else { |
1174 this.adapter_.sendKeyUpEvent('', code); | 1244 this.adapter_.sendKeyUpEvent('', code); |
1175 } | 1245 } |
1176 } | 1246 } |
1177 if (stateType == StateType.SHIFT) { | 1247 if (stateType == StateType.SHIFT) { |
1178 this.shiftForAutoCapital_ = false; | 1248 this.shiftForAutoCapital_ = false; |
1179 } | 1249 } |
1180 var isEnabledBefore = this.model_.stateManager.hasState(stateType); | 1250 var isEnabledBefore = this.model_.stateManager.hasState(stateType); |
1181 var isStickyBefore = this.model_.stateManager.isSticky(stateType); | 1251 var isStickyBefore = this.model_.stateManager.isSticky(stateType); |
1182 this.model_.stateManager.setState(stateType, enable); | 1252 this.model_.stateManager.setState(stateType, enable); |
1183 this.model_.stateManager.setSticky(stateType, isSticky); | 1253 this.model_.stateManager.setSticky(stateType, isSticky); |
1184 if (isEnabledBefore != enable || isStickyBefore != isSticky) { | 1254 var isFinalSticky = goog.isDef(opt_isFinalSticky) ? opt_isFinalSticky : |
| 1255 false; |
| 1256 var isFinalStikcyBefore = this.model_.stateManager.isFinalSticky(stateType); |
| 1257 this.model_.stateManager.setFinalSticky(stateType, isFinalSticky); |
| 1258 if (isEnabledBefore != enable || isStickyBefore != isSticky || |
| 1259 isFinalStikcyBefore != isFinalSticky) { |
1185 this.container_.update(); | 1260 this.container_.update(); |
1186 } | 1261 } |
1187 }; | 1262 }; |
1188 | 1263 |
1189 | 1264 |
1190 /** | 1265 /** |
1191 * Updates the modifier state for context. | 1266 * Updates the modifier state for context. |
1192 * | 1267 * |
1193 * @private | 1268 * @private |
1194 */ | 1269 */ |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1361 Controller.prototype.switchToKeySet = function(keyset) { | 1436 Controller.prototype.switchToKeySet = function(keyset) { |
1362 if (!this.isSettingReady) { | 1437 if (!this.isSettingReady) { |
1363 return; | 1438 return; |
1364 } | 1439 } |
1365 | 1440 |
1366 var lastKeysetView = this.container_.currentKeysetView; | 1441 var lastKeysetView = this.container_.currentKeysetView; |
1367 var ret = this.container_.switchToKeyset(this.getRemappedKeyset_(keyset), | 1442 var ret = this.container_.switchToKeyset(this.getRemappedKeyset_(keyset), |
1368 this.title_, this.adapter_.isPasswordBox(), this.adapter_.isA11yMode, | 1443 this.title_, this.adapter_.isPasswordBox(), this.adapter_.isA11yMode, |
1369 keyset, this.currentKeyset_, this.languageCode_); | 1444 keyset, this.currentKeyset_, this.languageCode_); |
1370 | 1445 |
1371 // Update the keyset of current context type. | 1446 if (!this.isSubKeyset_(this.currentKeyset_, keyset)) { |
1372 this.contextTypeToKeysetMap_[this.currentInputMethod_][ | 1447 // If it is the sub keyset switching, don't record it. |
1373 this.adapter_.getContextType()] = keyset; | 1448 // Update the keyset of current context type. |
| 1449 this.contextTypeToKeysetMap_[this.currentInputMethod_][ |
| 1450 this.adapter_.getContextType()] = keyset; |
| 1451 } |
1374 | 1452 |
1375 if (ret) { | 1453 if (ret) { |
1376 this.updateLanguageState_(this.currentKeyset_, keyset); | 1454 this.updateLanguageState_(this.currentKeyset_, keyset); |
1377 // Deactivate the last keyset view instance. | 1455 // Deactivate the last keyset view instance. |
1378 if (lastKeysetView) { | 1456 if (lastKeysetView) { |
1379 lastKeysetView.deactivate(this.currentKeyset_); | 1457 lastKeysetView.deactivate(this.currentKeyset_); |
1380 } | 1458 } |
1381 this.currentKeyset_ = keyset; | 1459 this.currentKeyset_ = keyset; |
1382 | 1460 |
1383 this.resize(Controller.DEV); | 1461 this.resize(Controller.DEV); |
1384 this.statistics_.setCurrentLayout(keyset); | 1462 this.statistics_.recordLayout(keyset, this.adapter_.isA11yMode); |
1385 // Activate the current key set view instance. | 1463 // Activate the current key set view instance. |
1386 this.container_.currentKeysetView.activate(keyset); | 1464 this.container_.currentKeysetView.activate(keyset); |
1387 this.perfTracker_.tick(PerfTracker.TickName.KEYBOARD_SHOWN); | 1465 this.perfTracker_.tick(PerfTracker.TickName.KEYBOARD_SHOWN); |
1388 this.perfTracker_.stop(); | 1466 this.perfTracker_.stop(); |
1389 } else { | 1467 } else { |
1390 this.loadResource_(keyset); | 1468 this.loadResource_(keyset); |
1391 } | 1469 } |
1392 }; | 1470 }; |
1393 | 1471 |
1394 | 1472 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1456 widthPercent = spec.HORIZONTAL; | 1534 widthPercent = spec.HORIZONTAL; |
1457 } | 1535 } |
1458 } else { | 1536 } else { |
1459 widthPercent = spec.VERTICAL; | 1537 widthPercent = spec.VERTICAL; |
1460 } | 1538 } |
1461 candidateViewHeight = SizeSpec.NON_A11Y_CANDIDATE_VIEW_HEIGHT; | 1539 candidateViewHeight = SizeSpec.NON_A11Y_CANDIDATE_VIEW_HEIGHT; |
1462 } | 1540 } |
1463 | 1541 |
1464 var viewportSize = goog.dom.getViewportSize(); | 1542 var viewportSize = goog.dom.getViewportSize(); |
1465 if (viewportSize.height != height && !opt_ignoreWindowResize) { | 1543 if (viewportSize.height != height && !opt_ignoreWindowResize) { |
1466 window.resizeTo(screen.width, height); | 1544 if (this.lastResizeHeight_ != height) { |
| 1545 this.lastResizeHeight_ = height; |
| 1546 window.resizeTo(screen.width, height); |
| 1547 } |
1467 return; | 1548 return; |
1468 } | 1549 } |
1469 | 1550 |
1470 this.container_.resize(screen.width, height, widthPercent, | 1551 this.container_.resize(screen.width, height, widthPercent, |
1471 candidateViewHeight); | 1552 candidateViewHeight); |
1472 if (this.container_.currentKeysetView) { | 1553 if (this.container_.currentKeysetView) { |
1473 this.isKeyboardReady = true; | 1554 this.isKeyboardReady = true; |
1474 } | 1555 } |
1475 }; | 1556 }; |
1476 | 1557 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1538 * | 1619 * |
1539 * @param {string} keyset The keyboard keyset. | 1620 * @param {string} keyset The keyboard keyset. |
1540 * @param {string} languageCode The language code for this keyboard. | 1621 * @param {string} languageCode The language code for this keyboard. |
1541 * @param {string} passwordLayout The layout for password box. | 1622 * @param {string} passwordLayout The layout for password box. |
1542 * @param {string} title The title for this keyboard. | 1623 * @param {string} title The title for this keyboard. |
1543 */ | 1624 */ |
1544 Controller.prototype.initialize = function(keyset, languageCode, passwordLayout, | 1625 Controller.prototype.initialize = function(keyset, languageCode, passwordLayout, |
1545 title) { | 1626 title) { |
1546 this.perfTracker_.restart(); | 1627 this.perfTracker_.restart(); |
1547 this.adapter_.getCurrentInputMethod(function(currentInputMethod) { | 1628 this.adapter_.getCurrentInputMethod(function(currentInputMethod) { |
| 1629 // TODO: remove this hack as soon as the manifest is fixed in chromium. |
| 1630 if (languageCode == 'ko') { |
| 1631 if (currentInputMethod.indexOf('hangul_2set') > 0) { |
| 1632 keyset = 'm17n:ko_2set'; |
| 1633 } |
| 1634 } |
1548 this.languageCode_ = languageCode; | 1635 this.languageCode_ = languageCode; |
1549 this.currentInputMethod_ = currentInputMethod; | 1636 this.currentInputMethod_ = currentInputMethod; |
1550 var keySetMap = this.contextTypeToKeysetMap_[this.currentInputMethod_]; | 1637 var keySetMap = this.contextTypeToKeysetMap_[this.currentInputMethod_]; |
1551 if (!keySetMap) { | 1638 if (!keySetMap) { |
1552 keySetMap = this.contextTypeToKeysetMap_[this.currentInputMethod_] = {}; | 1639 keySetMap = this.contextTypeToKeysetMap_[this.currentInputMethod_] = {}; |
1553 } | 1640 } |
1554 keySetMap[ContextType.PASSWORD] = passwordLayout; | 1641 keySetMap[ContextType.PASSWORD] = passwordLayout; |
1555 keySetMap[ContextType.DEFAULT] = keyset; | 1642 keySetMap[ContextType.DEFAULT] = keyset; |
1556 | 1643 |
1557 this.title_ = title; | 1644 this.title_ = title; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1634 | 1721 |
1635 /** | 1722 /** |
1636 * Updates the compact pinyin to set the inputcode for english and pinyin. | 1723 * Updates the compact pinyin to set the inputcode for english and pinyin. |
1637 * | 1724 * |
1638 * @param {string} fromRawKeyset . | 1725 * @param {string} fromRawKeyset . |
1639 * @param {string} toRawKeyset . | 1726 * @param {string} toRawKeyset . |
1640 * @private | 1727 * @private |
1641 */ | 1728 */ |
1642 Controller.prototype.updateLanguageState_ = | 1729 Controller.prototype.updateLanguageState_ = |
1643 function(fromRawKeyset, toRawKeyset) { | 1730 function(fromRawKeyset, toRawKeyset) { |
1644 if (fromRawKeyset == 'pinyin-zh-CN.en.compact.qwerty' && | 1731 var toggle = false; |
1645 toRawKeyset.indexOf('en.compact') == -1) { | 1732 var toggleState = false; |
1646 this.adapter_.toggleLanguageState(true); | 1733 // Deal with the switch logic to/from English within the compact layout. |
1647 } else if (fromRawKeyset.indexOf('en.compact') == -1 && | 1734 if (fromRawKeyset.indexOf('en.compact') * |
1648 toRawKeyset == 'pinyin-zh-CN.en.compact.qwerty') { | 1735 toRawKeyset.indexOf('en.compact') < 0) { // Switches between non-en/en. |
1649 this.adapter_.toggleLanguageState(false); | 1736 toggle = true; |
1650 } else if (goog.array.contains( | 1737 toggleState = toRawKeyset.indexOf('en.compact') == -1; |
1651 i18n.input.chrome.inputview.util.KEYSETS_HAVE_EN_SWTICHER, | 1738 } else if (fromRawKeyset.indexOf(toRawKeyset) == 0 && |
1652 toRawKeyset)) { | 1739 fromRawKeyset.indexOf('.compact') > 0 || |
1653 this.adapter_.toggleLanguageState(true); | 1740 fromRawKeyset && toRawKeyset.indexOf(fromRawKeyset) == 0 && |
1654 this.model_.stateManager.isEnMode = false; | 1741 toRawKeyset.indexOf('.compact') > 0) { |
| 1742 // Switch between full/compact layouts, reset the default button and |
| 1743 // language. |
| 1744 toggle = true; |
| 1745 toggleState = true; |
| 1746 } |
| 1747 if (toggle) { |
| 1748 this.adapter_.toggleLanguageState(toggleState); |
| 1749 this.model_.stateManager.isEnMode = !toggleState; |
1655 this.container_.currentKeysetView.update(); | 1750 this.container_.currentKeysetView.update(); |
1656 } | 1751 } |
1657 }; | 1752 }; |
| 1753 |
| 1754 |
| 1755 /** |
| 1756 * Records the stats which will be reported when input view is closing. |
| 1757 * |
| 1758 * @param {string} name The metrics name. |
| 1759 * @param {number} count The count value for histogram. |
| 1760 * @param {number} max . |
| 1761 * @param {number} bucketCount . |
| 1762 * @private |
| 1763 */ |
| 1764 Controller.prototype.recordStatsForClosing_ = function( |
| 1765 name, count, max, bucketCount) { |
| 1766 if (!this.statsForClosing_[name]) { |
| 1767 this.statsForClosing_[name] = [count, max, bucketCount]; |
| 1768 } else { |
| 1769 this.statsForClosing_[name][0] += count; |
| 1770 this.statsForClosing_[name][1] = max; |
| 1771 this.statsForClosing_[name][2] = bucketCount; |
| 1772 } |
| 1773 }; |
1658 }); // goog.scope | 1774 }); // goog.scope |
OLD | NEW |