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

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

Issue 674153004: Add third_party/google-input-tools: Take 2 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@google_input_tools
Patch Set: Created 6 years, 1 month 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
(Empty)
1 // Copyright 2014 The ChromeOS IME Authors. All Rights Reserved.
2 // limitations under the License.
3 // See the License for the specific language governing permissions and
4 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5 // distributed under the License is distributed on an "AS-IS" BASIS,
6 // Unless required by applicable law or agreed to in writing, software
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // You may obtain a copy of the License at
11 // you may not use this file except in compliance with the License.
12 // Licensed under the Apache License, Version 2.0 (the "License");
13 //
14 goog.provide('i18n.input.chrome.inputview.Adapter');
15
16 goog.require('goog.events.Event');
17 goog.require('goog.events.EventHandler');
18 goog.require('goog.events.EventTarget');
19 goog.require('goog.events.EventType');
20 goog.require('goog.object');
21 goog.require('i18n.input.chrome.DataSource');
22 goog.require('i18n.input.chrome.inputview.ReadyState');
23 goog.require('i18n.input.chrome.inputview.StateType');
24 goog.require('i18n.input.chrome.inputview.events.EventType');
25 goog.require('i18n.input.chrome.inputview.events.SurroundingTextChangedEvent');
26 goog.require('i18n.input.chrome.message.ContextType');
27 goog.require('i18n.input.chrome.message.Event');
28 goog.require('i18n.input.chrome.message.Name');
29 goog.require('i18n.input.chrome.message.Type');
30
31 goog.scope(function() {
32 var CandidatesBackEvent = i18n.input.chrome.DataSource.CandidatesBackEvent;
33 var ContextType = i18n.input.chrome.message.ContextType;
34 var Type = i18n.input.chrome.message.Type;
35 var Name = i18n.input.chrome.message.Name;
36
37
38
39 /**
40 * The adapter for interview.
41 *
42 * @param {!i18n.input.chrome.inputview.ReadyState} readyState .
43 * @extends {goog.events.EventTarget}
44 * @constructor
45 */
46 i18n.input.chrome.inputview.Adapter = function(readyState) {
47 goog.base(this);
48
49 /**
50 * Whether the keyboard is visible.
51 *
52 * @type {boolean}
53 */
54 this.isVisible = !document.webkitHidden;
55
56 /**
57 * The modifier state map.
58 *
59 * @type {!Object.<i18n.input.chrome.inputview.StateType, boolean>}
60 * @private
61 */
62 this.modifierState_ = {};
63
64 /**
65 * The system ready state.
66 *
67 * @private {!i18n.input.chrome.inputview.ReadyState}
68 */
69 this.readyState_ = readyState;
70
71 chrome.runtime.onMessage.addListener(this.onMessage_.bind(this));
72
73 /** @private {!goog.events.EventHandler} */
74 this.handler_ = new goog.events.EventHandler(this);
75 this.handler_.listen(document, 'webkitvisibilitychange',
76 this.onVisibilityChange_);
77 };
78 goog.inherits(i18n.input.chrome.inputview.Adapter,
79 goog.events.EventTarget);
80 var Adapter = i18n.input.chrome.inputview.Adapter;
81
82
83 /** @type {boolean} */
84 Adapter.prototype.isA11yMode = false;
85
86
87 /** @type {boolean} */
88 Adapter.prototype.isExperimental = false;
89
90
91 /** @type {boolean} */
92 Adapter.prototype.showGlobeKey = false;
93
94
95 /** @protected {string} */
96 Adapter.prototype.contextType = ContextType.DEFAULT;
97
98
99 /** @type {string} */
100 Adapter.prototype.screen = '';
101
102
103 /** @type {boolean} */
104 Adapter.prototype.isChromeVoxOn = false;
105
106
107 /** @type {string} */
108 Adapter.prototype.textBeforeCursor = '';
109
110
111 /**
112 * Callback for updating settings.
113 *
114 * @param {!Object} message .
115 * @private
116 */
117 Adapter.prototype.onUpdateSettings_ = function(message) {
118 this.contextType = message['contextType'];
119 this.screen = message['screen'];
120 this.dispatchEvent(new i18n.input.chrome.message.Event(Type.UPDATE_SETTINGS,
121 message));
122 };
123
124
125 /**
126 * Sets the modifier states.
127 *
128 * @param {i18n.input.chrome.inputview.StateType} stateType .
129 * @param {boolean} enable True to enable the state, false otherwise.
130 */
131 Adapter.prototype.setModifierState = function(stateType, enable) {
132 this.modifierState_[stateType] = enable;
133 };
134
135
136 /**
137 * Clears the modifier states.
138 */
139 Adapter.prototype.clearModifierStates = function() {
140 this.modifierState_ = {};
141 };
142
143
144 /**
145 * Simulates to send 'keydown' and 'keyup' event.
146 *
147 * @param {string} key
148 * @param {string} code
149 * @param {number=} opt_keyCode The key code.
150 * @param {!Object=} opt_spatialData .
151 */
152 Adapter.prototype.sendKeyDownAndUpEvent = function(key, code, opt_keyCode,
153 opt_spatialData) {
154 this.sendKeyEvent_([
155 this.generateKeyboardEvent_(
156 goog.events.EventType.KEYDOWN, key, code, opt_keyCode, opt_spatialData),
157 this.generateKeyboardEvent_(
158 goog.events.EventType.KEYUP, key, code, opt_keyCode, opt_spatialData)
159 ]);
160 };
161
162
163 /**
164 * Simulates to send 'keydown' event.
165 *
166 * @param {string} key
167 * @param {string} code
168 * @param {number=} opt_keyCode The key code.
169 * @param {!Object=} opt_spatialData .
170 */
171 Adapter.prototype.sendKeyDownEvent = function(key, code, opt_keyCode,
172 opt_spatialData) {
173 this.sendKeyEvent_([this.generateKeyboardEvent_(
174 goog.events.EventType.KEYDOWN, key, code, opt_keyCode,
175 opt_spatialData)]);
176 };
177
178
179 /**
180 * Simulates to send 'keyup' event.
181 *
182 * @param {string} key
183 * @param {string} code
184 * @param {number=} opt_keyCode The key code.
185 * @param {!Object=} opt_spatialData .
186 */
187 Adapter.prototype.sendKeyUpEvent = function(key, code, opt_keyCode,
188 opt_spatialData) {
189 this.sendKeyEvent_([this.generateKeyboardEvent_(
190 goog.events.EventType.KEYUP, key, code, opt_keyCode, opt_spatialData)]);
191 };
192
193
194 /**
195 * Use {@code chrome.input.ime.sendKeyEvents} to simulate key events.
196 *
197 * @param {!Array.<!Object.<string, string|boolean>>} keyData .
198 * @private
199 */
200 Adapter.prototype.sendKeyEvent_ = function(keyData) {
201 chrome.runtime.sendMessage(
202 goog.object.create(Name.MSG_TYPE, Type.SEND_KEY_EVENT, Name.KEY_DATA,
203 keyData));
204 };
205
206
207 /**
208 * Generates a {@code ChromeKeyboardEvent} by given values.
209 *
210 * @param {string} type .
211 * @param {string} key The key.
212 * @param {string} code The code.
213 * @param {number=} opt_keyCode The key code.
214 * @param {!Object=} opt_spatialData .
215 * @return {!Object.<string, string|boolean>}
216 * @private
217 */
218 Adapter.prototype.generateKeyboardEvent_ = function(
219 type, key, code, opt_keyCode, opt_spatialData) {
220 var StateType = i18n.input.chrome.inputview.StateType;
221 var ctrl = !!this.modifierState_[StateType.CTRL];
222 var alt = !!this.modifierState_[StateType.ALT];
223
224 if (ctrl || alt) {
225 key = '';
226 }
227 var result = {
228 'type': type,
229 'key': key,
230 'code': code,
231 'keyCode': opt_keyCode || 0,
232 'spatialData': opt_spatialData
233 };
234
235 result['altKey'] = alt;
236 result['ctrlKey'] = ctrl;
237 result['shiftKey'] = !!this.modifierState_[StateType.SHIFT];
238 result['capsLock'] = !!this.modifierState_[StateType.CAPSLOCK];
239
240 return result;
241 };
242
243
244 /**
245 * Callback when surrounding text is changed.
246 *
247 * @param {string} text .
248 * @private
249 */
250 Adapter.prototype.onSurroundingTextChanged_ = function(text) {
251 this.textBeforeCursor = text;
252 this.dispatchEvent(new i18n.input.chrome.inputview.events.
253 SurroundingTextChangedEvent(this.textBeforeCursor));
254 };
255
256
257 /**
258 * Gets the context.
259 *
260 * @return {string} .
261 */
262 Adapter.prototype.getContext = function() {
263 var matches = this.textBeforeCursor.match(/([a-zA-Z'-Ḁ-ỹÀ-ȳ]+)\s+$/);
264 var text = matches ? matches[1] : '';
265 return text;
266 };
267
268
269 /**
270 * Gets the context type.
271 *
272 * @return {string} .
273 */
274 Adapter.prototype.getContextType = function() {
275 return this.contextType || ContextType.DEFAULT;
276 };
277
278
279 /**
280 * Sends request for handwriting.
281 *
282 * @param {!Object} payload .
283 */
284 Adapter.prototype.sendHwtRequest = function(payload) {
285 chrome.runtime.sendMessage(goog.object.create(
286 Name.MSG_TYPE, Type.HWT_REQUEST, Name.MSG, payload
287 ));
288 };
289
290
291 /**
292 * True if it is a password box.
293 *
294 * @return {boolean} .
295 */
296 Adapter.prototype.isPasswordBox = function() {
297 return this.contextType == 'password';
298 };
299
300
301 /**
302 * Callback when blurs in the context.
303 *
304 * @private
305 */
306 Adapter.prototype.onContextBlur_ = function() {
307 this.contextType = '';
308 this.dispatchEvent(new goog.events.Event(i18n.input.chrome.inputview.events.
309 EventType.CONTEXT_BLUR));
310 };
311
312
313 /**
314 * Callback when focus on a context.
315 *
316 * @param {string} contextType .
317 * @private
318 */
319 Adapter.prototype.onContextFocus_ = function(contextType) {
320 this.contextType = contextType;
321 this.dispatchEvent(new goog.events.Event(i18n.input.chrome.inputview.events.
322 EventType.CONTEXT_FOCUS));
323 };
324
325
326 /**
327 * Intializes the communication to background page.
328 *
329 * @param {string} languageCode The language code.
330 * @private
331 */
332 Adapter.prototype.initBackground_ = function(languageCode) {
333 chrome.runtime.getBackgroundPage((function() {
334 chrome.runtime.sendMessage(
335 goog.object.create(Name.MSG_TYPE, Type.CONNECT));
336 chrome.runtime.sendMessage(goog.object.create(Name.MSG_TYPE,
337 Type.VISIBILITY_CHANGE, Name.VISIBILITY, !document.webkitHidden));
338 if (languageCode) {
339 this.setLanguage(languageCode);
340 }
341 }).bind(this));
342 };
343
344
345 /**
346 * Loads the keyboard settings.
347 *
348 * @param {string} languageCode The language code.
349 */
350 Adapter.prototype.initialize = function(languageCode) {
351 if (chrome.accessibilityFeatures &&
352 chrome.accessibilityFeatures.spokenFeedback) {
353 chrome.accessibilityFeatures.spokenFeedback.get({}, (function(details) {
354 this.isChromeVoxOn = details['value'];
355 }).bind(this));
356 chrome.accessibilityFeatures.spokenFeedback.onChange.addListener((function(
357 details) {
358 this.isChromeVoxOn = details['value'];
359 }).bind(this));
360 }
361
362 this.initBackground_(languageCode);
363
364 var StateType = i18n.input.chrome.inputview.ReadyState.StateType;
365 if (window.inputview) {
366 if (inputview.getKeyboardConfig) {
367 inputview.getKeyboardConfig((function(config) {
368 this.isA11yMode = !!config['a11ymode'];
369 this.isExperimental = !!config['experimental'];
370 this.readyState_.markStateReady(StateType.KEYBOARD_CONFIG_READY);
371 if (this.readyState_.isReady(StateType.IME_LIST_READY)) {
372 this.dispatchEvent(new goog.events.Event(
373 i18n.input.chrome.inputview.events.EventType.SETTINGS_READY));
374 }
375 }).bind(this));
376 } else {
377 this.readyState_.markStateReady(StateType.KEYBOARD_CONFIG_READY);
378 }
379 if (inputview.getInputMethods) {
380 inputview.getInputMethods((function(inputMethods) {
381 // Only show globe key to switching between IMEs when there are more
382 // than one IME.
383 this.showGlobeKey = inputMethods.length > 1;
384 this.readyState_.markStateReady(StateType.IME_LIST_READY);
385 if (this.readyState_.isReady(StateType.KEYBOARD_CONFIG_READY)) {
386 this.dispatchEvent(new goog.events.Event(
387 i18n.input.chrome.inputview.events.EventType.SETTINGS_READY));
388 }
389 }).bind(this));
390 } else {
391 this.readyState_.markStateReady(StateType.IME_LIST_READY);
392 }
393 } else {
394 this.readyState_.markStateReady(StateType.IME_LIST_READY);
395 this.readyState_.markStateReady(StateType.KEYBOARD_CONFIG_READY);
396 }
397
398 if (this.readyState_.isReady(StateType.KEYBOARD_CONFIG_READY) &&
399 this.readyState_.isReady(StateType.IME_LIST_READY)) {
400 window.setTimeout((function() {
401 this.dispatchEvent(new goog.events.Event(
402 i18n.input.chrome.inputview.events.EventType.SETTINGS_READY));
403 }).bind(this), 0);
404 }
405 };
406
407
408 /**
409 * Gets the currently activated input method.
410 *
411 * @param {function(string)} callback .
412 */
413 Adapter.prototype.getCurrentInputMethod = function(callback) {
414 if (window.inputview && inputview.getCurrentInputMethod) {
415 inputview.getCurrentInputMethod(callback);
416 } else {
417 callback('DU');
418 }
419 };
420
421
422 /**
423 * Gets the list of all activated input methods.
424 *
425 * @param {function(Array.<Object>)} callback .
426 */
427 Adapter.prototype.getInputMethods = function(callback) {
428 if (window.inputview && inputview.getInputMethods) {
429 inputview.getInputMethods(callback);
430 } else {
431 // Provides a dummy IME item to enable IME switcher UI.
432 callback([
433 {'indicator': 'DU', 'id': 'DU', 'name': 'Dummy IME', 'command': 1}]);
434 }
435 };
436
437
438 /**
439 * Switches to the input method with id equals |inputMethodId|.
440 *
441 * @param {!string} inputMethodId .
442 */
443 Adapter.prototype.switchToInputMethod = function(inputMethodId) {
444 if (window.inputview && inputview.switchToInputMethod) {
445 inputview.switchToInputMethod(inputMethodId);
446 }
447 };
448
449
450 /**
451 * Callback for visibility change on the input view window.
452 *
453 * @private
454 */
455 Adapter.prototype.onVisibilityChange_ = function() {
456 this.isVisible = !document.webkitHidden;
457 this.dispatchEvent(new goog.events.Event(i18n.input.chrome.inputview.
458 events.EventType.VISIBILITY_CHANGE));
459 chrome.runtime.sendMessage(goog.object.create(Name.MSG_TYPE,
460 Type.VISIBILITY_CHANGE, Name.VISIBILITY, !document.webkitHidden));
461 };
462
463
464 /**
465 * Sends request for completion.
466 *
467 * @param {string} query .
468 * @param {!Object=} opt_spatialData .
469 */
470 Adapter.prototype.sendCompletionRequest = function(query, opt_spatialData) {
471 var spatialData = {};
472 if (opt_spatialData) {
473 spatialData[Name.SOURCES] = opt_spatialData.sources;
474 spatialData[Name.POSSIBILITIES] = opt_spatialData.possibilities;
475 }
476 chrome.runtime.sendMessage(goog.object.create(Name.MSG_TYPE,
477 Type.COMPLETION, Name.TEXT, query, Name.SPATIAL_DATA, spatialData));
478 };
479
480
481 /**
482 * Selects the candidate.
483 *
484 * @param {!Object} candidate .
485 */
486 Adapter.prototype.selectCandidate = function(candidate) {
487 chrome.runtime.sendMessage(goog.object.create(
488 Name.MSG_TYPE, Type.SELECT_CANDIDATE, Name.CANDIDATE, candidate));
489 };
490
491
492 /**
493 * Commits the text.
494 *
495 * @param {string} text .
496 */
497 Adapter.prototype.commitText = function(text) {
498 chrome.runtime.sendMessage(goog.object.create(
499 Name.MSG_TYPE, Type.COMMIT_TEXT, Name.TEXT, text));
500 };
501
502
503 /**
504 * Sets the language.
505 *
506 * @param {string} language .
507 */
508 Adapter.prototype.setLanguage = function(language) {
509 chrome.runtime.sendMessage(goog.object.create(
510 Name.MSG_TYPE, Type.SET_LANGUAGE, Name.LANGUAGE, language));
511 };
512
513
514 /**
515 * Callbck when completion is back.
516 *
517 * @param {!Object} message .
518 * @private
519 */
520 Adapter.prototype.onCandidatesBack_ = function(message) {
521 var source = message['source'] || '';
522 var candidates = message['candidates'] || [];
523 this.dispatchEvent(new CandidatesBackEvent(source, candidates));
524 };
525
526
527 /**
528 * Hides the keyboard.
529 */
530 Adapter.prototype.hideKeyboard = function() {
531 chrome.input.ime.hideInputView();
532 };
533
534
535 /**
536 * Sends Input Tool code to background.
537 *
538 * @param {string} inputToolCode .
539 */
540 Adapter.prototype.setInputToolCode = function(inputToolCode) {
541 chrome.runtime.sendMessage(
542 goog.object.create(
543 Name.MSG_TYPE,
544 Type.HWT_SET_INPUTTOOL,
545 Name.MSG,
546 inputToolCode));
547 };
548
549
550 /**
551 * Sends DOUBLE_CLICK_ON_SPACE_KEY message.
552 */
553 Adapter.prototype.doubleClickOnSpaceKey = function() {
554 chrome.runtime.sendMessage(
555 goog.object.create(
556 Name.MSG_TYPE,
557 Type.DOUBLE_CLICK_ON_SPACE_KEY));
558 };
559
560
561 /**
562 * Sends message to the background when switch to emoji.
563 *
564 */
565 Adapter.prototype.setEmojiInputToolCode = function() {
566 chrome.runtime.sendMessage(
567 goog.object.create(
568 Name.MSG_TYPE,
569 Type.EMOJI_SET_INPUTTOOL));
570 };
571
572
573 /**
574 * Sends message to the background when do internal inputtool switch.
575 *
576 * @param {boolean} inputToolValue The value of the language flag.
577 */
578 Adapter.prototype.toggleLanguageState = function(inputToolValue) {
579 chrome.runtime.sendMessage(
580 goog.object.create(
581 Name.MSG_TYPE,
582 Type.TOGGLE_LANGUAGE_STATE,
583 Name.MSG,
584 inputToolValue));
585 };
586
587
588 /**
589 * Sends unset Input Tool code to background.
590 */
591 Adapter.prototype.unsetInputToolCode = function() {
592 chrome.runtime.sendMessage(
593 goog.object.create(
594 Name.MSG_TYPE,
595 Type.HWT_UNSET_INPUTTOOL));
596 };
597
598
599 /**
600 * Sends message to the background when switch to other mode from emoji.
601 *
602 */
603 Adapter.prototype.unsetEmojiInputToolCode = function() {
604 chrome.runtime.sendMessage(
605 goog.object.create(
606 Name.MSG_TYPE,
607 Type.EMOJI_UNSET_INPUTTOOL));
608 };
609
610
611 /**
612 * Processes incoming message from option page or inputview window.
613 *
614 * @param {*} request Message from option page or inputview window.
615 * @param {*} sender Information about the script
616 * context that sent the message.
617 * @param {function(*): void} sendResponse Function to call to send a response.
618 * @return {boolean|undefined} {@code true} to keep the message channel open in
619 * order to send a response asynchronously.
620 * @private
621 */
622 Adapter.prototype.onMessage_ = function(request, sender, sendResponse) {
623 var type = request[Name.MSG_TYPE];
624 var msg = request[Name.MSG];
625 switch (type) {
626 case Type.CANDIDATES_BACK:
627 this.onCandidatesBack_(msg);
628 break;
629 case Type.CONTEXT_FOCUS:
630 this.onContextFocus_(request[Name.CONTEXT_TYPE]);
631 break;
632 case Type.CONTEXT_BLUR:
633 this.onContextBlur_();
634 break;
635 case Type.SURROUNDING_TEXT_CHANGED:
636 this.onSurroundingTextChanged_(request[Name.TEXT]);
637 break;
638 case Type.UPDATE_SETTINGS:
639 this.onUpdateSettings_(msg);
640 break;
641 case Type.HWT_NETWORK_ERROR:
642 case Type.HWT_PRIVACY_INFO:
643 this.dispatchEvent(new i18n.input.chrome.message.Event(type, msg));
644 break;
645 }
646 };
647
648
649 /**
650 * Sends the privacy confirmed message to background and broadcasts it.
651 */
652 Adapter.prototype.sendHwtPrivacyConfirmMessage = function() {
653 chrome.runtime.sendMessage(
654 goog.object.create(Name.MSG_TYPE, Type.HWT_PRIVACY_GOT_IT));
655 this.dispatchEvent(
656 new goog.events.Event(Type.HWT_PRIVACY_GOT_IT));
657 };
658
659
660 /** @override */
661 Adapter.prototype.disposeInternal = function() {
662 goog.dispose(this.handler_);
663
664 goog.base(this, 'disposeInternal');
665 };
666 }); // goog.scope
667
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698