Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java
41152 views
1
/*
2
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.awt;
27
28
import java.awt.AWTException;
29
import java.awt.event.InputMethodEvent;
30
import java.awt.font.TextAttribute;
31
import java.awt.font.TextHitInfo;
32
import java.awt.peer.ComponentPeer;
33
import java.text.AttributedString;
34
35
import sun.util.logging.PlatformLogger;
36
37
/**
38
* Input Method Adapter for XIM
39
*
40
* @author JavaSoft International
41
*/
42
public abstract class X11InputMethod extends X11InputMethodBase {
43
44
/**
45
* Constructs an X11InputMethod instance. It initializes the XIM
46
* environment if it's not done yet.
47
*
48
* @exception AWTException if XOpenIM() failed.
49
*/
50
public X11InputMethod() throws AWTException {
51
super();
52
}
53
54
/**
55
* Reset the composition state to the current composition state.
56
*/
57
protected void resetCompositionState() {
58
if (compositionEnableSupported && haveActiveClient()) {
59
try {
60
/* Restore the composition mode to the last saved composition
61
mode. */
62
setCompositionEnabled(savedCompositionState);
63
} catch (UnsupportedOperationException e) {
64
compositionEnableSupported = false;
65
}
66
}
67
}
68
69
/**
70
* Activate input method.
71
*/
72
public synchronized void activate() {
73
clientComponentWindow = getClientComponentWindow();
74
if (clientComponentWindow == null)
75
return;
76
77
if (lastXICFocussedComponent != null) {
78
if (log.isLoggable(PlatformLogger.Level.FINE)) {
79
log.fine("XICFocused {0}, AWTFocused {1}",
80
lastXICFocussedComponent, awtFocussedComponent);
81
}
82
}
83
84
if (pData == 0) {
85
if (!createXIC()) {
86
return;
87
}
88
disposed = false;
89
}
90
91
/* reset input context if necessary and set the XIC focus
92
*/
93
resetXICifneeded();
94
ComponentPeer lastXICFocussedComponentPeer = null;
95
ComponentPeer awtFocussedComponentPeer = getPeer(awtFocussedComponent);
96
97
if (lastXICFocussedComponent != null) {
98
lastXICFocussedComponentPeer = getPeer(lastXICFocussedComponent);
99
}
100
101
/* If the last XIC focussed component has a different peer as the
102
current focussed component, change the XIC focus to the newly
103
focussed component.
104
*/
105
if (isLastTemporary || lastXICFocussedComponentPeer != awtFocussedComponentPeer ||
106
isLastXICActive != haveActiveClient()) {
107
if (lastXICFocussedComponentPeer != null) {
108
setXICFocus(lastXICFocussedComponentPeer, false, isLastXICActive);
109
}
110
if (awtFocussedComponentPeer != null) {
111
setXICFocus(awtFocussedComponentPeer, true, haveActiveClient());
112
}
113
lastXICFocussedComponent = awtFocussedComponent;
114
isLastXICActive = haveActiveClient();
115
}
116
resetCompositionState();
117
isActive = true;
118
}
119
120
/**
121
* Deactivate input method.
122
*/
123
public synchronized void deactivate(boolean isTemporary) {
124
boolean isAc = haveActiveClient();
125
/* Usually as the client component, let's call it component A,
126
loses the focus, this method is called. Then when another client
127
component, let's call it component B, gets the focus, activate is first called on
128
the previous focused compoent which is A, then endComposition is called on A,
129
deactivate is called on A again. And finally activate is called on the newly
130
focused component B. Here is the call sequence.
131
132
A loses focus B gains focus
133
-------------> deactivate A -------------> activate A -> endComposition A ->
134
deactivate A -> activate B ----....
135
136
So in order to carry the composition mode across the components sharing the same
137
input context, we save it when deactivate is called so that when activate is
138
called, it can be restored correctly till activate is called on the newly focused
139
component. (See also sun/awt/im/InputContext and bug 6184471).
140
Last note, getCompositionState should be called before setXICFocus since
141
setXICFocus here sets the XIC to 0.
142
*/
143
savedCompositionState = getCompositionState();
144
145
if (isTemporary) {
146
//turn the status window off...
147
turnoffStatusWindow();
148
}
149
150
/* Delay resetting the XIC focus until activate is called and the newly
151
* Focused component has a different peer as the last focused component.
152
*/
153
lastXICFocussedComponent = awtFocussedComponent;
154
isLastXICActive = isAc;
155
isLastTemporary = isTemporary;
156
isActive = false;
157
}
158
159
// implements java.awt.im.spi.InputMethod.hideWindows
160
public void hideWindows() {
161
// ??? need real implementation
162
}
163
164
/**
165
* Updates composed text with XIM preedit information and
166
* posts composed text to the awt event queue. The args of
167
* this method correspond to the XIM preedit callback
168
* information. The XIM highlight attributes are translated via
169
* fixed mapping (i.e., independent from any underlying input
170
* method engine). This method is invoked in the AWT Toolkit
171
* (X event loop) thread context and thus inside the AWT Lock.
172
*/
173
// NOTE: This method may be called by privileged threads.
174
// This functionality is implemented in a package-private method
175
// to insure that it cannot be overridden by client subclasses.
176
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
177
void dispatchComposedText(String chgText,
178
int[] chgStyles,
179
int chgOffset,
180
int chgLength,
181
int caretPosition,
182
long when) {
183
if (disposed) {
184
return;
185
}
186
187
// Workaround for deadlock bug on solaris2.6_zh bug#4170760
188
if (chgText == null
189
&& chgStyles == null
190
&& chgOffset == 0
191
&& chgLength == 0
192
&& caretPosition == 0
193
&& composedText == null
194
&& committedText == null)
195
return;
196
197
if (composedText == null) {
198
// TODO: avoid reallocation of those buffers
199
composedText = new StringBuffer(INITIAL_SIZE);
200
rawFeedbacks = new IntBuffer(INITIAL_SIZE);
201
}
202
if (chgLength > 0) {
203
if (chgText == null && chgStyles != null) {
204
rawFeedbacks.replace(chgOffset, chgStyles);
205
} else {
206
if (chgLength == composedText.length()) {
207
// optimization for the special case to replace the
208
// entire previous text
209
composedText = new StringBuffer(INITIAL_SIZE);
210
rawFeedbacks = new IntBuffer(INITIAL_SIZE);
211
} else {
212
if (composedText.length() > 0) {
213
if (chgOffset+chgLength < composedText.length()) {
214
String text;
215
text = composedText.toString().substring(chgOffset+chgLength,
216
composedText.length());
217
composedText.setLength(chgOffset);
218
composedText.append(text);
219
} else {
220
// in case to remove substring from chgOffset
221
// to the end
222
composedText.setLength(chgOffset);
223
}
224
rawFeedbacks.remove(chgOffset, chgLength);
225
}
226
}
227
}
228
}
229
if (chgText != null) {
230
composedText.insert(chgOffset, chgText);
231
if (chgStyles != null)
232
rawFeedbacks.insert(chgOffset, chgStyles);
233
}
234
235
if (composedText.length() == 0) {
236
composedText = null;
237
rawFeedbacks = null;
238
239
// if there is any outstanding committed text stored by
240
// dispatchCommittedText(), it has to be sent to the
241
// client component.
242
if (committedText != null) {
243
dispatchCommittedText(committedText, when);
244
committedText = null;
245
return;
246
}
247
248
// otherwise, send null text to delete client's composed
249
// text.
250
postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
251
null,
252
0,
253
null,
254
null,
255
when);
256
257
return;
258
}
259
260
// Now sending the composed text to the client
261
int composedOffset;
262
AttributedString inputText;
263
264
// if there is any partially committed text, concatenate it to
265
// the composed text.
266
if (committedText != null) {
267
composedOffset = committedText.length();
268
inputText = new AttributedString(committedText + composedText);
269
committedText = null;
270
} else {
271
composedOffset = 0;
272
inputText = new AttributedString(composedText.toString());
273
}
274
275
int currentFeedback;
276
int nextFeedback;
277
int startOffset = 0;
278
int currentOffset;
279
int visiblePosition = 0;
280
TextHitInfo visiblePositionInfo = null;
281
282
rawFeedbacks.rewind();
283
currentFeedback = rawFeedbacks.getNext();
284
rawFeedbacks.unget();
285
while ((nextFeedback = rawFeedbacks.getNext()) != -1) {
286
if (visiblePosition == 0) {
287
visiblePosition = nextFeedback & XIMVisibleMask;
288
if (visiblePosition != 0) {
289
int index = rawFeedbacks.getOffset() - 1;
290
291
if (visiblePosition == XIMVisibleToBackward)
292
visiblePositionInfo = TextHitInfo.leading(index);
293
else
294
visiblePositionInfo = TextHitInfo.trailing(index);
295
}
296
}
297
nextFeedback &= ~XIMVisibleMask;
298
if (currentFeedback != nextFeedback) {
299
rawFeedbacks.unget();
300
currentOffset = rawFeedbacks.getOffset();
301
inputText.addAttribute(TextAttribute.INPUT_METHOD_HIGHLIGHT,
302
convertVisualFeedbackToHighlight(currentFeedback),
303
composedOffset + startOffset,
304
composedOffset + currentOffset);
305
startOffset = currentOffset;
306
currentFeedback = nextFeedback;
307
}
308
}
309
currentOffset = rawFeedbacks.getOffset();
310
if (currentOffset >= 0) {
311
inputText.addAttribute(TextAttribute.INPUT_METHOD_HIGHLIGHT,
312
convertVisualFeedbackToHighlight(currentFeedback),
313
composedOffset + startOffset,
314
composedOffset + currentOffset);
315
}
316
317
postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
318
inputText.getIterator(),
319
composedOffset,
320
TextHitInfo.leading(caretPosition),
321
visiblePositionInfo,
322
when);
323
}
324
325
/*
326
* Subclasses should override disposeImpl() instead of dispose(). Client
327
* code should always invoke dispose(), never disposeImpl().
328
*/
329
protected synchronized void disposeImpl() {
330
disposeXIC();
331
awtLock();
332
composedText = null;
333
committedText = null;
334
rawFeedbacks = null;
335
awtUnlock();
336
awtFocussedComponent = null;
337
lastXICFocussedComponent = null;
338
}
339
340
/**
341
* @see java.awt.im.spi.InputMethod#setCompositionEnabled(boolean)
342
*/
343
public void setCompositionEnabled(boolean enable) {
344
/* If the composition state is successfully changed, set
345
the savedCompositionState to 'enable'. Otherwise, simply
346
return.
347
setCompositionEnabledNative may throw UnsupportedOperationException.
348
Don't try to catch it since the method may be called by clients.
349
Use package private mthod 'resetCompositionState' if you want the
350
exception to be caught.
351
*/
352
if (setCompositionEnabledNative(enable)) {
353
savedCompositionState = enable;
354
}
355
}
356
}
357
358