This repository has been archived by the owner on Nov 3, 2021. It is now read-only.
/
layout_rendering_manager.js
235 lines (184 loc) · 8.2 KB
/
layout_rendering_manager.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
'use strict';
/* global IMERender, Promise */
(function(exports) {
var LayoutRenderingManager = function(app) {
this.app = app;
// Reference of the layoutManager.currentPage that is
// currently being rendered. Only updates when updateLayoutRendering()
// is called.
this._currentRenderingPage = null;
this._resizeListenerTimer = undefined;
// a weak map from DOM elements to its abstract key object, to keep us from
// directly relying on DOM elements during user interactions.
// this should only be directly written by IMErender,
// and reading should always take place through |getTargetObject| below.
this.domObjectMap = null;
};
LayoutRenderingManager.prototype.start = function() {
this.app.console.log('LayoutRenderingManager.start()');
// We cannot listen to resize event right at start because of
// https://bugzil.la/1007595 ;
// only attach the event listener after 2000ms.
this._resizeListenerTimer = setTimeout(function attachResizeListener() {
this.app.console.log('LayoutRenderingManager.attachResizeListener()');
// Handle resize events
window.addEventListener('resize', this);
}.bind(this), 2000);
this.domObjectMap = new WeakMap();
};
LayoutRenderingManager.prototype.stop = function() {
clearTimeout(this._resizeListenerTimer);
this._resizeListenerTimer = undefined;
window.removeEventListener('resize', this);
this.domObjectMap = null;
};
LayoutRenderingManager.prototype.handleEvent = function() {
this.app.console.log('LayoutRenderingManager.handleEvent()');
if (document.hidden) {
this.app.console.log(
'LayoutRenderingManager: Ignore resizing call since ' +
'document is hidden.');
return;
}
if (this._currentRenderingPage !== this.app.layoutManager.currentPage) {
this.app.console.log(
'LayoutRenderingManager: Ignore resizing call since ' +
'layout is not ready yet.');
return;
}
IMERender.resizeUI(this.app.layoutManager.currentPage);
this._updateHeight();
// TODO: need to check how to handle orientation change case to
// show current word suggestions
this._updateLayoutParams();
};
LayoutRenderingManager.prototype.updateCandidatesRendering = function() {
if (this._currentRenderingPage !== this.app.layoutManager.currentPage) {
this.app.console.log(
'LayoutRenderingManager: Ignore updateCandidatesRendering() call since ' +
'layout is not ready yet.');
return;
}
IMERender.showCandidates(this.app.candidatePanelManager.currentCandidates);
};
LayoutRenderingManager.prototype.updateUpperCaseRendering = function() {
this.app.console.log('LayoutRenderingManager.updateUpperCaseRendering()');
if (this._currentRenderingPage !== this.app.layoutManager.currentPage) {
this.app.console.log(
'LayoutRenderingManager: Ignore updateUpperCaseRendering() call since ' +
'layout is not ready yet.');
return;
}
// Otherwise we can just update only the keys we need...
// Try to block the event loop as little as possible
window.requestAnimationFrame(function() {
this.app.console.log(
'LayoutRenderingManager.updateUpperCaseRendering()::' +
'requestAnimationFrame');
IMERender.setUpperCaseLock(this.app.upperCaseStateManager);
}.bind(this));
};
// This function asks render.js to create an HTML layout for the keyboard.
//
// This should be called when the keyboard changes or when the layout page
// changes in order to actually render the layout.
LayoutRenderingManager.prototype.updateLayoutRendering = function() {
this.app.console.log('LayoutRenderingManager.updateLayoutRendering()');
this.app.console.time('LayoutRenderingManager.updateLayoutRendering()');
var currentPage = this._currentRenderingPage =
this.app.layoutManager.currentPage;
var currentIMEngine = this.app.inputMethodManager.currentIMEngine;
this.app.console.log('needsCandidatePanel',
currentPage.autoCorrectLanguage, currentPage.needsCandidatePanel,
typeof currentIMEngine.displaysCandidates !== 'function',
(currentIMEngine.displaysCandidates &&
currentIMEngine.displaysCandidates()));
// Determine if the candidate panel for word suggestion is needed
var needsCandidatePanel = !!(
(currentPage.autoCorrectLanguage || currentPage.needsCandidatePanel) &&
((typeof currentIMEngine.displaysCandidates !== 'function') ||
currentIMEngine.displaysCandidates()));
var p = new Promise(function(resolve) {
IMERender.draw(currentPage, {
uppercase: this.app.upperCaseStateManager.isUpperCase,
inputType: this.app.getBasicInputType(),
showCandidatePanel: needsCandidatePanel
}, resolve);
}.bind(this)).then(this._afterRenderDrew.bind(this));
// Make sure JS error is not sliently ignored.
p.catch(function(e) { console.error(e); });
this.app.console.timeEnd('LayoutRenderingManager.updateLayoutRendering()');
return p;
};
LayoutRenderingManager.prototype.drawHandwritingPad = function(press,
start,
strokeWidth) {
return IMERender.drawHandwritingPad(press, start, strokeWidth);
};
LayoutRenderingManager.prototype.clearHandwritingPad = function(target) {
IMERender.clearHandwritingPad(target);
};
// So there are a couple of things that we want don't want to block
// on here, so we can do it if resizeUI is fully finished
LayoutRenderingManager.prototype._afterRenderDrew = function() {
this.app.console.log('LayoutRenderingManager._afterRenderDrew()');
this.app.console.time('LayoutRenderingManager._afterRenderDrew()');
// Reflect the current upper case state on the newly rendered layout.
IMERender.setUpperCaseLock(this.app.upperCaseStateManager);
// Reflect the current candidates on the current layout.
IMERender.showCandidates(this.app.candidatePanelManager.currentCandidates);
// Tell the input method about the new keyboard layout
this._updateLayoutParams();
// Show the keyboard or update to the current height.
this._updateHeight();
this.app.console.timeEnd('LayoutRenderingManager._afterRenderDrew()');
};
// If the input method cares about layout details, get those details
// from the renderer and pass them on to the input method. This is called
// from renderKeyboard() each time the keyboard layout changes.
// As an optimzation, however, we only send parameters if layoutPage is
// the default, since the input methods we support don't do anything special
// for symbols.
LayoutRenderingManager.prototype._updateLayoutParams = function() {
this.app.console.log('LayoutRenderingManager._updateLayoutParams()');
var currentIMEngine = this.app.inputMethodManager.currentIMEngine;
var layoutManager = this.app.layoutManager;
if ((typeof currentIMEngine.setLayoutParams !== 'function') ||
layoutManager.currentPageIndex !== layoutManager.PAGE_INDEX_DEFAULT) {
return;
}
var candidatePanel = IMERender.candidatePanel;
var yBias = candidatePanel ? candidatePanel.clientHeight : 0;
currentIMEngine.setLayoutParams({
keyboardWidth: IMERender.getWidth(),
keyboardHeight: (IMERender.getHeight() - yBias),
keyArray: IMERender.getKeyArray(),
keyWidth: IMERender.getKeyWidth(),
keyHeight: IMERender.getKeyHeight()
});
};
LayoutRenderingManager.prototype._updateHeight = function() {
this.app.console.log('LayoutRenderingManager._updateHeight()');
this.app.console.time('LayoutRenderingManager._updateHeight()');
// height of the current active IME + 1px for the borderTop
var imeHeight = IMERender.getHeight() + 1;
var imeWidth = IMERender.getWidth();
this.app.console.timeEnd('LayoutRenderingManager._updateHeight()');
this.app.console.timeEnd('activate');
this.app.console.timeEnd('domLoading');
window.resizeTo(imeWidth, imeHeight);
};
LayoutRenderingManager.prototype.getTargetObject = function (elem) {
this.app.console.log(
'LayoutRenderingManager.getTargetObject()', elem);
if (!elem) {
return {};
}
var target = this.domObjectMap.get(elem);
this.app.console.log('target=', target,
'prototype=', target && Object.getPrototypeOf(target));
// default to an empty object such that member accessing and 'in' won't fail
return target || {};
};
exports.LayoutRenderingManager = LayoutRenderingManager;
})(window);