author | prr |
Sat, 19 Sep 2015 15:45:59 -0700 | |
changeset 32865 | f9cb6e427f9e |
parent 32491 | 7b3783f9484d |
child 44534 | a076dffbc2c1 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
30938
35ae5c70d60e
8030087: Avoid public native methods in sun.awt packages
serb
parents:
25859
diff
changeset
|
2 |
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. |
2 | 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 |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 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 |
* |
|
5506 | 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. |
|
2 | 24 |
*/ |
25 |
||
26 |
package sun.awt; |
|
27 |
||
28 |
import java.util.Collections; |
|
29 |
import java.util.Locale; |
|
30 |
import java.util.Map; |
|
31 |
import java.util.HashMap; |
|
32 |
import java.awt.AWTEvent; |
|
33 |
import java.awt.AWTException; |
|
34 |
import java.awt.Component; |
|
35 |
import java.awt.Container; |
|
36 |
import java.awt.EventQueue; |
|
37 |
import java.awt.Window; |
|
38 |
import java.awt.im.InputMethodHighlight; |
|
39 |
import java.awt.im.spi.InputMethodContext; |
|
40 |
import sun.awt.im.InputMethodAdapter; |
|
41 |
import java.awt.event.InputMethodEvent; |
|
42 |
import java.awt.font.TextAttribute; |
|
43 |
import java.awt.font.TextHitInfo; |
|
44 |
import java.awt.peer.ComponentPeer; |
|
45 |
import java.lang.Character.Subset; |
|
46 |
import java.text.AttributedString; |
|
47 |
import java.text.AttributedCharacterIterator; |
|
48 |
||
49 |
import java.io.File; |
|
50 |
import java.io.FileReader; |
|
51 |
import java.io.BufferedReader; |
|
52 |
import java.io.IOException; |
|
15638 | 53 |
import java.lang.ref.WeakReference; |
3938
ef327bd847c0
6879044: Eliminate the dependency on logging from the AWT/2D/Swing classes
mchung
parents:
2
diff
changeset
|
54 |
import sun.util.logging.PlatformLogger; |
2 | 55 |
import java.util.StringTokenizer; |
56 |
import java.util.regex.Pattern; |
|
57 |
||
58 |
||
59 |
/** |
|
60 |
* Input Method Adapter for XIM |
|
61 |
* |
|
62 |
* @author JavaSoft International |
|
63 |
*/ |
|
64 |
public abstract class X11InputMethod extends InputMethodAdapter { |
|
3938
ef327bd847c0
6879044: Eliminate the dependency on logging from the AWT/2D/Swing classes
mchung
parents:
2
diff
changeset
|
65 |
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11InputMethod"); |
2 | 66 |
/* |
67 |
* The following XIM* values must be the same as those defined in |
|
68 |
* Xlib.h |
|
69 |
*/ |
|
70 |
private static final int XIMReverse = (1<<0); |
|
71 |
private static final int XIMUnderline = (1<<1); |
|
72 |
private static final int XIMHighlight = (1<<2); |
|
73 |
private static final int XIMPrimary = (1<<5); |
|
74 |
private static final int XIMSecondary = (1<<6); |
|
75 |
private static final int XIMTertiary = (1<<7); |
|
76 |
||
77 |
/* |
|
78 |
* visible position values |
|
79 |
*/ |
|
80 |
private static final int XIMVisibleToForward = (1<<8); |
|
81 |
private static final int XIMVisibleToBackward = (1<<9); |
|
82 |
private static final int XIMVisibleCenter = (1<<10); |
|
83 |
private static final int XIMVisibleMask = (XIMVisibleToForward| |
|
84 |
XIMVisibleToBackward| |
|
85 |
XIMVisibleCenter); |
|
86 |
||
87 |
private Locale locale; |
|
88 |
private static boolean isXIMOpened = false; |
|
89 |
protected Container clientComponentWindow = null; |
|
90 |
private Component awtFocussedComponent = null; |
|
91 |
private Component lastXICFocussedComponent = null; |
|
92 |
private boolean isLastXICActive = false; |
|
6839
1e57288ce186
6575419: Solaris : XSetICFoucs is not called with Java application at appropriate timing
naoto
parents:
5506
diff
changeset
|
93 |
private boolean isLastTemporary = false; |
2 | 94 |
private boolean isActive = false; |
95 |
private boolean isActiveClient = false; |
|
24538
25bf8153fbfe
8039642: Fix raw and unchecked warnings in sun.awt.*
henryjen
parents:
23010
diff
changeset
|
96 |
private static Map<TextAttribute, ?>[] highlightStyles; |
2 | 97 |
private boolean disposed = false; |
98 |
||
99 |
//reset the XIC if necessary |
|
100 |
private boolean needResetXIC = false; |
|
15638 | 101 |
private WeakReference<Component> needResetXICClient = new WeakReference<>(null); |
2 | 102 |
|
103 |
// The use of compositionEnableSupported is to reduce unnecessary |
|
104 |
// native calls if set/isCompositionEnabled |
|
105 |
// throws UnsupportedOperationException. |
|
106 |
// It is set to false if that exception is thrown first time |
|
107 |
// either of the two methods are called. |
|
108 |
private boolean compositionEnableSupported = true; |
|
109 |
// The savedCompositionState indicates the composition mode when |
|
110 |
// endComposition or setCompositionEnabled is called. It doesn't always |
|
111 |
// reflect the actual composition state because it doesn't get updated |
|
112 |
// when the user changes the composition state through direct interaction |
|
113 |
// with the input method. It is used to save the composition mode when |
|
114 |
// focus is traversed across different client components sharing the |
|
115 |
// same java input context. Also if set/isCompositionEnabled are not |
|
116 |
// supported, it remains false. |
|
117 |
private boolean savedCompositionState = false; |
|
118 |
||
119 |
// variables to keep track of preedit context. |
|
120 |
// these variables need to be accessed within AWT_LOCK/UNLOCK |
|
121 |
private String committedText = null; |
|
122 |
private StringBuffer composedText = null; |
|
123 |
private IntBuffer rawFeedbacks; |
|
124 |
||
125 |
// private data (X11InputMethodData structure defined in |
|
126 |
// awt_InputMethod.c) for native methods |
|
127 |
// this structure needs to be accessed within AWT_LOCK/UNLOCK |
|
32865
f9cb6e427f9e
8136783: Run blessed-modifier-order script on java.desktop
prr
parents:
32491
diff
changeset
|
128 |
private transient long pData = 0; // accessed by native |
2 | 129 |
|
130 |
// Initialize highlight mapping table |
|
131 |
static { |
|
24538
25bf8153fbfe
8039642: Fix raw and unchecked warnings in sun.awt.*
henryjen
parents:
23010
diff
changeset
|
132 |
@SuppressWarnings({"unchecked", "rawtypes"}) |
25bf8153fbfe
8039642: Fix raw and unchecked warnings in sun.awt.*
henryjen
parents:
23010
diff
changeset
|
133 |
Map<TextAttribute, ?> styles[] = new Map[4]; |
25bf8153fbfe
8039642: Fix raw and unchecked warnings in sun.awt.*
henryjen
parents:
23010
diff
changeset
|
134 |
HashMap<TextAttribute, Object> map; |
2 | 135 |
|
136 |
// UNSELECTED_RAW_TEXT_HIGHLIGHT |
|
24538
25bf8153fbfe
8039642: Fix raw and unchecked warnings in sun.awt.*
henryjen
parents:
23010
diff
changeset
|
137 |
map = new HashMap<>(1); |
25bf8153fbfe
8039642: Fix raw and unchecked warnings in sun.awt.*
henryjen
parents:
23010
diff
changeset
|
138 |
map.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD); |
2 | 139 |
styles[0] = Collections.unmodifiableMap(map); |
140 |
||
141 |
// SELECTED_RAW_TEXT_HIGHLIGHT |
|
24538
25bf8153fbfe
8039642: Fix raw and unchecked warnings in sun.awt.*
henryjen
parents:
23010
diff
changeset
|
142 |
map = new HashMap<>(1); |
25bf8153fbfe
8039642: Fix raw and unchecked warnings in sun.awt.*
henryjen
parents:
23010
diff
changeset
|
143 |
map.put(TextAttribute.SWAP_COLORS, TextAttribute.SWAP_COLORS_ON); |
2 | 144 |
styles[1] = Collections.unmodifiableMap(map); |
145 |
||
146 |
// UNSELECTED_CONVERTED_TEXT_HIGHLIGHT |
|
24538
25bf8153fbfe
8039642: Fix raw and unchecked warnings in sun.awt.*
henryjen
parents:
23010
diff
changeset
|
147 |
map = new HashMap<>(1); |
2 | 148 |
map.put(TextAttribute.INPUT_METHOD_UNDERLINE, |
24538
25bf8153fbfe
8039642: Fix raw and unchecked warnings in sun.awt.*
henryjen
parents:
23010
diff
changeset
|
149 |
TextAttribute.UNDERLINE_LOW_ONE_PIXEL); |
2 | 150 |
styles[2] = Collections.unmodifiableMap(map); |
151 |
||
152 |
// SELECTED_CONVERTED_TEXT_HIGHLIGHT |
|
24538
25bf8153fbfe
8039642: Fix raw and unchecked warnings in sun.awt.*
henryjen
parents:
23010
diff
changeset
|
153 |
map = new HashMap<>(1); |
25bf8153fbfe
8039642: Fix raw and unchecked warnings in sun.awt.*
henryjen
parents:
23010
diff
changeset
|
154 |
map.put(TextAttribute.SWAP_COLORS, TextAttribute.SWAP_COLORS_ON); |
2 | 155 |
styles[3] = Collections.unmodifiableMap(map); |
156 |
||
157 |
highlightStyles = styles; |
|
158 |
} |
|
159 |
||
160 |
static { |
|
161 |
initIDs(); |
|
162 |
} |
|
163 |
||
164 |
/** |
|
165 |
* Initialize JNI field and method IDs for fields that may be |
|
166 |
accessed from C. |
|
167 |
*/ |
|
168 |
private static native void initIDs(); |
|
169 |
||
170 |
/** |
|
171 |
* Constructs an X11InputMethod instance. It initializes the XIM |
|
172 |
* environment if it's not done yet. |
|
173 |
* |
|
174 |
* @exception AWTException if XOpenIM() failed. |
|
175 |
*/ |
|
176 |
public X11InputMethod() throws AWTException { |
|
177 |
// supports only the locale in which the VM is started |
|
178 |
locale = X11InputMethodDescriptor.getSupportedLocale(); |
|
179 |
if (initXIM() == false) { |
|
180 |
throw new AWTException("Cannot open X Input Method"); |
|
181 |
} |
|
182 |
} |
|
183 |
||
184 |
protected void finalize() throws Throwable { |
|
185 |
dispose(); |
|
186 |
super.finalize(); |
|
187 |
} |
|
188 |
||
189 |
/** |
|
190 |
* Invokes openIM() that invokes XOpenIM() if it's not opened yet. |
|
191 |
* @return true if openXIM() is successful or it's already been opened. |
|
192 |
*/ |
|
193 |
private synchronized boolean initXIM() { |
|
194 |
if (isXIMOpened == false) |
|
195 |
isXIMOpened = openXIM(); |
|
196 |
return isXIMOpened; |
|
197 |
} |
|
198 |
||
199 |
protected abstract boolean openXIM(); |
|
200 |
||
201 |
protected boolean isDisposed() { |
|
202 |
return disposed; |
|
203 |
} |
|
204 |
||
205 |
protected abstract void setXICFocus(ComponentPeer peer, |
|
206 |
boolean value, boolean active); |
|
207 |
||
208 |
/** |
|
209 |
* Does nothing - this adapter doesn't use the input method context. |
|
210 |
* |
|
211 |
* @see java.awt.im.spi.InputMethod#setInputMethodContext |
|
212 |
*/ |
|
213 |
public void setInputMethodContext(InputMethodContext context) { |
|
214 |
} |
|
215 |
||
216 |
/** |
|
217 |
* Set locale to input. If input method doesn't support specified locale, |
|
218 |
* false will be returned and its behavior is not changed. |
|
219 |
* |
|
220 |
* @param lang locale to input |
|
221 |
* @return the true is returned when specified locale is supported. |
|
222 |
*/ |
|
223 |
public boolean setLocale(Locale lang) { |
|
224 |
if (lang.equals(locale)) { |
|
225 |
return true; |
|
226 |
} |
|
227 |
// special compatibility rule for Japanese and Korean |
|
228 |
if (locale.equals(Locale.JAPAN) && lang.equals(Locale.JAPANESE) || |
|
229 |
locale.equals(Locale.KOREA) && lang.equals(Locale.KOREAN)) { |
|
230 |
return true; |
|
231 |
} |
|
232 |
return false; |
|
233 |
} |
|
234 |
||
235 |
/** |
|
236 |
* Returns current input locale. |
|
237 |
*/ |
|
238 |
public Locale getLocale() { |
|
239 |
return locale; |
|
240 |
} |
|
241 |
||
242 |
/** |
|
243 |
* Does nothing - XIM doesn't let you specify which characters you expect. |
|
244 |
* |
|
245 |
* @see java.awt.im.spi.InputMethod#setCharacterSubsets |
|
246 |
*/ |
|
247 |
public void setCharacterSubsets(Subset[] subsets) { |
|
248 |
} |
|
249 |
||
250 |
/** |
|
251 |
* Dispatch event to input method. InputContext dispatch event with this |
|
252 |
* method. Input method set consume flag if event is consumed in |
|
253 |
* input method. |
|
254 |
* |
|
255 |
* @param e event |
|
256 |
*/ |
|
257 |
public void dispatchEvent(AWTEvent e) { |
|
258 |
} |
|
259 |
||
260 |
||
261 |
protected final void resetXICifneeded(){ |
|
262 |
/* needResetXIC is used to indicate whether to call |
|
263 |
resetXIC on the active client. resetXIC will always be |
|
264 |
called on the passive client when endComposition is called. |
|
265 |
*/ |
|
266 |
if (needResetXIC && haveActiveClient() && |
|
15638 | 267 |
getClientComponent() != needResetXICClient.get()){ |
2 | 268 |
resetXIC(); |
269 |
||
270 |
// needs to reset the last xic focussed component. |
|
271 |
lastXICFocussedComponent = null; |
|
272 |
isLastXICActive = false; |
|
273 |
||
15638 | 274 |
needResetXICClient.clear(); |
2 | 275 |
needResetXIC = false; |
276 |
} |
|
277 |
} |
|
278 |
||
279 |
/** |
|
280 |
* Reset the composition state to the current composition state. |
|
281 |
*/ |
|
282 |
private void resetCompositionState() { |
|
283 |
if (compositionEnableSupported) { |
|
284 |
try { |
|
285 |
/* Restore the composition mode to the last saved composition |
|
286 |
mode. */ |
|
287 |
setCompositionEnabled(savedCompositionState); |
|
288 |
} catch (UnsupportedOperationException e) { |
|
289 |
compositionEnableSupported = false; |
|
290 |
} |
|
291 |
} |
|
292 |
} |
|
293 |
||
294 |
/** |
|
295 |
* Query and then return the current composition state. |
|
32491
7b3783f9484d
8133807: java.desktop docs: replace some invalid "@returns" tags
avstepan
parents:
30948
diff
changeset
|
296 |
* @return the composition state if isCompositionEnabled call |
2 | 297 |
* is successful. Otherwise, it returns false. |
298 |
*/ |
|
299 |
private boolean getCompositionState() { |
|
300 |
boolean compositionState = false; |
|
301 |
if (compositionEnableSupported) { |
|
302 |
try { |
|
303 |
compositionState = isCompositionEnabled(); |
|
304 |
} catch (UnsupportedOperationException e) { |
|
305 |
compositionEnableSupported = false; |
|
306 |
} |
|
307 |
} |
|
308 |
return compositionState; |
|
309 |
} |
|
310 |
||
311 |
/** |
|
312 |
* Activate input method. |
|
313 |
*/ |
|
314 |
public synchronized void activate() { |
|
315 |
clientComponentWindow = getClientComponentWindow(); |
|
316 |
if (clientComponentWindow == null) |
|
317 |
return; |
|
318 |
||
319 |
if (lastXICFocussedComponent != null){ |
|
18178
ee71c923891d
8016747: Replace deprecated PlatformLogger isLoggable(int) with isLoggable(Level)
chegar
parents:
16839
diff
changeset
|
320 |
if (log.isLoggable(PlatformLogger.Level.FINE)) { |
16839
d0f2e97b7359
8010297: Missing isLoggable() checks in logging code
anthony
parents:
15638
diff
changeset
|
321 |
log.fine("XICFocused {0}, AWTFocused {1}", |
d0f2e97b7359
8010297: Missing isLoggable() checks in logging code
anthony
parents:
15638
diff
changeset
|
322 |
lastXICFocussedComponent, awtFocussedComponent); |
d0f2e97b7359
8010297: Missing isLoggable() checks in logging code
anthony
parents:
15638
diff
changeset
|
323 |
} |
2 | 324 |
} |
325 |
||
326 |
if (pData == 0) { |
|
327 |
if (!createXIC()) { |
|
328 |
return; |
|
329 |
} |
|
330 |
disposed = false; |
|
331 |
} |
|
332 |
||
333 |
/* reset input context if necessary and set the XIC focus |
|
334 |
*/ |
|
335 |
resetXICifneeded(); |
|
336 |
ComponentPeer lastXICFocussedComponentPeer = null; |
|
337 |
ComponentPeer awtFocussedComponentPeer = getPeer(awtFocussedComponent); |
|
338 |
||
339 |
if (lastXICFocussedComponent != null) { |
|
340 |
lastXICFocussedComponentPeer = getPeer(lastXICFocussedComponent); |
|
341 |
} |
|
342 |
||
343 |
/* If the last XIC focussed component has a different peer as the |
|
344 |
current focussed component, change the XIC focus to the newly |
|
345 |
focussed component. |
|
346 |
*/ |
|
6839
1e57288ce186
6575419: Solaris : XSetICFoucs is not called with Java application at appropriate timing
naoto
parents:
5506
diff
changeset
|
347 |
if (isLastTemporary || lastXICFocussedComponentPeer != awtFocussedComponentPeer || |
2 | 348 |
isLastXICActive != haveActiveClient()) { |
349 |
if (lastXICFocussedComponentPeer != null) { |
|
350 |
setXICFocus(lastXICFocussedComponentPeer, false, isLastXICActive); |
|
351 |
} |
|
352 |
if (awtFocussedComponentPeer != null) { |
|
353 |
setXICFocus(awtFocussedComponentPeer, true, haveActiveClient()); |
|
354 |
} |
|
355 |
lastXICFocussedComponent = awtFocussedComponent; |
|
356 |
isLastXICActive = haveActiveClient(); |
|
357 |
} |
|
358 |
resetCompositionState(); |
|
359 |
isActive = true; |
|
360 |
} |
|
361 |
||
362 |
protected abstract boolean createXIC(); |
|
363 |
||
364 |
/** |
|
365 |
* Deactivate input method. |
|
366 |
*/ |
|
367 |
public synchronized void deactivate(boolean isTemporary) { |
|
368 |
boolean isAc = haveActiveClient(); |
|
369 |
/* Usually as the client component, let's call it component A, |
|
370 |
loses the focus, this method is called. Then when another client |
|
371 |
component, let's call it component B, gets the focus, activate is first called on |
|
372 |
the previous focused compoent which is A, then endComposition is called on A, |
|
373 |
deactivate is called on A again. And finally activate is called on the newly |
|
374 |
focused component B. Here is the call sequence. |
|
375 |
||
376 |
A loses focus B gains focus |
|
377 |
-------------> deactivate A -------------> activate A -> endComposition A -> |
|
378 |
deactivate A -> activate B ----.... |
|
379 |
||
380 |
So in order to carry the composition mode across the components sharing the same |
|
381 |
input context, we save it when deactivate is called so that when activate is |
|
382 |
called, it can be restored correctly till activate is called on the newly focused |
|
383 |
component. (See also sun/awt/im/InputContext and bug 6184471). |
|
384 |
Last note, getCompositionState should be called before setXICFocus since |
|
385 |
setXICFocus here sets the XIC to 0. |
|
386 |
*/ |
|
387 |
savedCompositionState = getCompositionState(); |
|
388 |
||
389 |
if (isTemporary){ |
|
390 |
//turn the status window off... |
|
391 |
turnoffStatusWindow(); |
|
392 |
} |
|
393 |
||
394 |
/* Delay resetting the XIC focus until activate is called and the newly |
|
395 |
focussed component has a different peer as the last focussed component. |
|
396 |
*/ |
|
397 |
lastXICFocussedComponent = awtFocussedComponent; |
|
398 |
isLastXICActive = isAc; |
|
6839
1e57288ce186
6575419: Solaris : XSetICFoucs is not called with Java application at appropriate timing
naoto
parents:
5506
diff
changeset
|
399 |
isLastTemporary = isTemporary; |
2 | 400 |
isActive = false; |
401 |
} |
|
402 |
||
403 |
/** |
|
404 |
* Explicitly disable the native IME. Native IME is not disabled when |
|
405 |
* deactivate is called. |
|
406 |
*/ |
|
407 |
public void disableInputMethod() { |
|
408 |
if (lastXICFocussedComponent != null) { |
|
409 |
setXICFocus(getPeer(lastXICFocussedComponent), false, isLastXICActive); |
|
410 |
lastXICFocussedComponent = null; |
|
411 |
isLastXICActive = false; |
|
14498
317e4103662e
6789984: JPasswordField can not receive keyboard input
alitvinov
parents:
7668
diff
changeset
|
412 |
|
317e4103662e
6789984: JPasswordField can not receive keyboard input
alitvinov
parents:
7668
diff
changeset
|
413 |
resetXIC(); |
15638 | 414 |
needResetXICClient.clear(); |
14498
317e4103662e
6789984: JPasswordField can not receive keyboard input
alitvinov
parents:
7668
diff
changeset
|
415 |
needResetXIC = false; |
2 | 416 |
} |
417 |
} |
|
418 |
||
419 |
// implements java.awt.im.spi.InputMethod.hideWindows |
|
420 |
public void hideWindows() { |
|
421 |
// ??? need real implementation |
|
422 |
} |
|
423 |
||
424 |
/** |
|
425 |
* @see java.awt.Toolkit#mapInputMethodHighlight |
|
426 |
*/ |
|
24538
25bf8153fbfe
8039642: Fix raw and unchecked warnings in sun.awt.*
henryjen
parents:
23010
diff
changeset
|
427 |
public static Map<TextAttribute, ?> mapInputMethodHighlight(InputMethodHighlight highlight) { |
2 | 428 |
int index; |
429 |
int state = highlight.getState(); |
|
430 |
if (state == InputMethodHighlight.RAW_TEXT) { |
|
431 |
index = 0; |
|
432 |
} else if (state == InputMethodHighlight.CONVERTED_TEXT) { |
|
433 |
index = 2; |
|
434 |
} else { |
|
435 |
return null; |
|
436 |
} |
|
437 |
if (highlight.isSelected()) { |
|
438 |
index += 1; |
|
439 |
} |
|
440 |
return highlightStyles[index]; |
|
441 |
} |
|
442 |
||
443 |
/** |
|
444 |
* @see sun.awt.im.InputMethodAdapter#setAWTFocussedComponent |
|
445 |
*/ |
|
446 |
protected void setAWTFocussedComponent(Component component) { |
|
447 |
if (component == null) { |
|
448 |
return; |
|
449 |
} |
|
450 |
if (isActive) { |
|
451 |
// deactivate/activate are being suppressed during a focus change - |
|
452 |
// this may happen when an input method window is made visible |
|
453 |
boolean ac = haveActiveClient(); |
|
454 |
setXICFocus(getPeer(awtFocussedComponent), false, ac); |
|
455 |
setXICFocus(getPeer(component), true, ac); |
|
456 |
} |
|
457 |
awtFocussedComponent = component; |
|
458 |
} |
|
459 |
||
460 |
/** |
|
461 |
* @see sun.awt.im.InputMethodAdapter#stopListening |
|
462 |
*/ |
|
463 |
protected void stopListening() { |
|
464 |
// It is desirable to disable XIM by calling XSetICValues with |
|
465 |
// XNPreeditState == XIMPreeditDisable. But Solaris 2.6 and |
|
466 |
// Solaris 7 do not implement this correctly without a patch, |
|
467 |
// so just call resetXIC here. Prior endComposition call commits |
|
468 |
// the existing composed text. |
|
469 |
endComposition(); |
|
470 |
// disable the native input method so that the other input |
|
471 |
// method could get the input focus. |
|
472 |
disableInputMethod(); |
|
473 |
if (needResetXIC) { |
|
474 |
resetXIC(); |
|
15638 | 475 |
needResetXICClient.clear(); |
2 | 476 |
needResetXIC = false; |
477 |
} |
|
478 |
} |
|
479 |
||
480 |
/** |
|
481 |
* Returns the Window instance in which the client component is |
|
482 |
* contained. If not found, null is returned. (IS THIS POSSIBLE?) |
|
483 |
*/ |
|
484 |
// NOTE: This method may be called by privileged threads. |
|
485 |
// DO NOT INVOKE CLIENT CODE ON THIS THREAD! |
|
486 |
private Window getClientComponentWindow() { |
|
487 |
Component client = getClientComponent(); |
|
488 |
Container container; |
|
489 |
||
490 |
if (client instanceof Container) { |
|
491 |
container = (Container) client; |
|
492 |
} else { |
|
493 |
container = getParent(client); |
|
494 |
} |
|
495 |
||
496 |
while (container != null && !(container instanceof java.awt.Window)) { |
|
497 |
container = getParent(container); |
|
498 |
} |
|
499 |
return (Window) container; |
|
500 |
} |
|
501 |
||
502 |
protected abstract Container getParent(Component client); |
|
503 |
||
504 |
/** |
|
505 |
* Returns peer of the given client component. If the given client component |
|
506 |
* doesn't have peer, peer of the native container of the client is returned. |
|
507 |
*/ |
|
508 |
protected abstract ComponentPeer getPeer(Component client); |
|
509 |
||
510 |
/** |
|
511 |
* Used to protect preedit data |
|
512 |
*/ |
|
513 |
protected abstract void awtLock(); |
|
514 |
protected abstract void awtUnlock(); |
|
515 |
||
516 |
/** |
|
517 |
* Creates an input method event from the arguments given |
|
518 |
* and posts it on the AWT event queue. For arguments, |
|
519 |
* see InputMethodEvent. Called by input method. |
|
520 |
* |
|
521 |
* @see java.awt.event.InputMethodEvent#InputMethodEvent |
|
522 |
*/ |
|
523 |
private void postInputMethodEvent(int id, |
|
524 |
AttributedCharacterIterator text, |
|
525 |
int committedCharacterCount, |
|
526 |
TextHitInfo caret, |
|
527 |
TextHitInfo visiblePosition, |
|
528 |
long when) { |
|
529 |
Component source = getClientComponent(); |
|
530 |
if (source != null) { |
|
531 |
InputMethodEvent event = new InputMethodEvent(source, |
|
532 |
id, when, text, committedCharacterCount, caret, visiblePosition); |
|
533 |
SunToolkit.postEvent(SunToolkit.targetToAppContext(source), (AWTEvent)event); |
|
534 |
} |
|
535 |
} |
|
536 |
||
537 |
private void postInputMethodEvent(int id, |
|
538 |
AttributedCharacterIterator text, |
|
539 |
int committedCharacterCount, |
|
540 |
TextHitInfo caret, |
|
541 |
TextHitInfo visiblePosition) { |
|
542 |
postInputMethodEvent(id, text, committedCharacterCount, |
|
543 |
caret, visiblePosition, EventQueue.getMostRecentEventTime()); |
|
544 |
} |
|
545 |
||
546 |
/** |
|
547 |
* Dispatches committed text from XIM to the awt event queue. This |
|
548 |
* method is invoked from the event handler in canvas.c in the |
|
549 |
* AWT Toolkit thread context and thus inside the AWT Lock. |
|
550 |
* @param str committed text |
|
30948
0a0972d3b58d
6587235: Incorrect javadoc: "no parameter" in 2d source code
serb
parents:
30938
diff
changeset
|
551 |
* @param when when |
2 | 552 |
*/ |
553 |
// NOTE: This method may be called by privileged threads. |
|
554 |
// This functionality is implemented in a package-private method |
|
555 |
// to insure that it cannot be overridden by client subclasses. |
|
556 |
// DO NOT INVOKE CLIENT CODE ON THIS THREAD! |
|
557 |
void dispatchCommittedText(String str, long when) { |
|
558 |
if (str == null) |
|
559 |
return; |
|
560 |
||
561 |
if (composedText == null) { |
|
562 |
AttributedString attrstr = new AttributedString(str); |
|
563 |
postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, |
|
564 |
attrstr.getIterator(), |
|
565 |
str.length(), |
|
566 |
null, |
|
567 |
null, |
|
568 |
when); |
|
569 |
} else { |
|
570 |
// if there is composed text, wait until the preedit |
|
571 |
// callback is invoked. |
|
572 |
committedText = str; |
|
573 |
} |
|
574 |
} |
|
575 |
||
576 |
private void dispatchCommittedText(String str) { |
|
577 |
dispatchCommittedText(str, EventQueue.getMostRecentEventTime()); |
|
578 |
} |
|
579 |
||
580 |
/** |
|
581 |
* Updates composed text with XIM preedit information and |
|
582 |
* posts composed text to the awt event queue. The args of |
|
583 |
* this method correspond to the XIM preedit callback |
|
584 |
* information. The XIM highlight attributes are translated via |
|
585 |
* fixed mapping (i.e., independent from any underlying input |
|
586 |
* method engine). This method is invoked in the AWT Toolkit |
|
587 |
* (X event loop) thread context and thus inside the AWT Lock. |
|
588 |
*/ |
|
589 |
// NOTE: This method may be called by privileged threads. |
|
590 |
// This functionality is implemented in a package-private method |
|
591 |
// to insure that it cannot be overridden by client subclasses. |
|
592 |
// DO NOT INVOKE CLIENT CODE ON THIS THREAD! |
|
593 |
void dispatchComposedText(String chgText, |
|
594 |
int chgStyles[], |
|
595 |
int chgOffset, |
|
596 |
int chgLength, |
|
597 |
int caretPosition, |
|
598 |
long when) { |
|
599 |
if (disposed) { |
|
600 |
return; |
|
601 |
} |
|
602 |
||
603 |
//Workaround for deadlock bug on solaris2.6_zh bug#4170760 |
|
604 |
if (chgText == null |
|
605 |
&& chgStyles == null |
|
606 |
&& chgOffset == 0 |
|
607 |
&& chgLength == 0 |
|
608 |
&& caretPosition == 0 |
|
609 |
&& composedText == null |
|
610 |
&& committedText == null) |
|
611 |
return; |
|
612 |
||
613 |
if (composedText == null) { |
|
614 |
// TODO: avoid reallocation of those buffers |
|
615 |
composedText = new StringBuffer(INITIAL_SIZE); |
|
616 |
rawFeedbacks = new IntBuffer(INITIAL_SIZE); |
|
617 |
} |
|
618 |
if (chgLength > 0) { |
|
619 |
if (chgText == null && chgStyles != null) { |
|
620 |
rawFeedbacks.replace(chgOffset, chgStyles); |
|
621 |
} else { |
|
622 |
if (chgLength == composedText.length()) { |
|
623 |
// optimization for the special case to replace the |
|
624 |
// entire previous text |
|
625 |
composedText = new StringBuffer(INITIAL_SIZE); |
|
626 |
rawFeedbacks = new IntBuffer(INITIAL_SIZE); |
|
627 |
} else { |
|
628 |
if (composedText.length() > 0) { |
|
629 |
if (chgOffset+chgLength < composedText.length()) { |
|
630 |
String text; |
|
631 |
text = composedText.toString().substring(chgOffset+chgLength, |
|
632 |
composedText.length()); |
|
633 |
composedText.setLength(chgOffset); |
|
634 |
composedText.append(text); |
|
635 |
} else { |
|
636 |
// in case to remove substring from chgOffset |
|
637 |
// to the end |
|
638 |
composedText.setLength(chgOffset); |
|
639 |
} |
|
640 |
rawFeedbacks.remove(chgOffset, chgLength); |
|
641 |
} |
|
642 |
} |
|
643 |
} |
|
644 |
} |
|
645 |
if (chgText != null) { |
|
646 |
composedText.insert(chgOffset, chgText); |
|
647 |
if (chgStyles != null) |
|
648 |
rawFeedbacks.insert(chgOffset, chgStyles); |
|
649 |
} |
|
650 |
||
651 |
if (composedText.length() == 0) { |
|
652 |
composedText = null; |
|
653 |
rawFeedbacks = null; |
|
654 |
||
655 |
// if there is any outstanding committed text stored by |
|
656 |
// dispatchCommittedText(), it has to be sent to the |
|
657 |
// client component. |
|
658 |
if (committedText != null) { |
|
659 |
dispatchCommittedText(committedText, when); |
|
660 |
committedText = null; |
|
661 |
return; |
|
662 |
} |
|
663 |
||
664 |
// otherwise, send null text to delete client's composed |
|
665 |
// text. |
|
666 |
postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, |
|
667 |
null, |
|
668 |
0, |
|
669 |
null, |
|
670 |
null, |
|
671 |
when); |
|
672 |
||
673 |
return; |
|
674 |
} |
|
675 |
||
676 |
// Now sending the composed text to the client |
|
677 |
int composedOffset; |
|
678 |
AttributedString inputText; |
|
679 |
||
680 |
// if there is any partially committed text, concatenate it to |
|
681 |
// the composed text. |
|
682 |
if (committedText != null) { |
|
683 |
composedOffset = committedText.length(); |
|
684 |
inputText = new AttributedString(committedText + composedText); |
|
685 |
committedText = null; |
|
686 |
} else { |
|
687 |
composedOffset = 0; |
|
688 |
inputText = new AttributedString(composedText.toString()); |
|
689 |
} |
|
690 |
||
691 |
int currentFeedback; |
|
692 |
int nextFeedback; |
|
693 |
int startOffset = 0; |
|
694 |
int currentOffset; |
|
695 |
int visiblePosition = 0; |
|
696 |
TextHitInfo visiblePositionInfo = null; |
|
697 |
||
698 |
rawFeedbacks.rewind(); |
|
699 |
currentFeedback = rawFeedbacks.getNext(); |
|
700 |
rawFeedbacks.unget(); |
|
701 |
while ((nextFeedback = rawFeedbacks.getNext()) != -1) { |
|
702 |
if (visiblePosition == 0) { |
|
703 |
visiblePosition = nextFeedback & XIMVisibleMask; |
|
704 |
if (visiblePosition != 0) { |
|
705 |
int index = rawFeedbacks.getOffset() - 1; |
|
706 |
||
707 |
if (visiblePosition == XIMVisibleToBackward) |
|
708 |
visiblePositionInfo = TextHitInfo.leading(index); |
|
709 |
else |
|
710 |
visiblePositionInfo = TextHitInfo.trailing(index); |
|
711 |
} |
|
712 |
} |
|
713 |
nextFeedback &= ~XIMVisibleMask; |
|
714 |
if (currentFeedback != nextFeedback) { |
|
715 |
rawFeedbacks.unget(); |
|
716 |
currentOffset = rawFeedbacks.getOffset(); |
|
717 |
inputText.addAttribute(TextAttribute.INPUT_METHOD_HIGHLIGHT, |
|
718 |
convertVisualFeedbackToHighlight(currentFeedback), |
|
719 |
composedOffset + startOffset, |
|
720 |
composedOffset + currentOffset); |
|
721 |
startOffset = currentOffset; |
|
722 |
currentFeedback = nextFeedback; |
|
723 |
} |
|
724 |
} |
|
725 |
currentOffset = rawFeedbacks.getOffset(); |
|
726 |
if (currentOffset >= 0) { |
|
727 |
inputText.addAttribute(TextAttribute.INPUT_METHOD_HIGHLIGHT, |
|
728 |
convertVisualFeedbackToHighlight(currentFeedback), |
|
729 |
composedOffset + startOffset, |
|
730 |
composedOffset + currentOffset); |
|
731 |
} |
|
732 |
||
733 |
postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, |
|
734 |
inputText.getIterator(), |
|
735 |
composedOffset, |
|
736 |
TextHitInfo.leading(caretPosition), |
|
737 |
visiblePositionInfo, |
|
738 |
when); |
|
739 |
} |
|
740 |
||
741 |
/** |
|
742 |
* Flushes composed and committed text held in this context. |
|
743 |
* This method is invoked in the AWT Toolkit (X event loop) thread context |
|
744 |
* and thus inside the AWT Lock. |
|
745 |
*/ |
|
746 |
// NOTE: This method may be called by privileged threads. |
|
747 |
// This functionality is implemented in a package-private method |
|
748 |
// to insure that it cannot be overridden by client subclasses. |
|
749 |
// DO NOT INVOKE CLIENT CODE ON THIS THREAD! |
|
750 |
void flushText() { |
|
751 |
String flush = (committedText != null ? committedText : ""); |
|
752 |
if (composedText != null) { |
|
753 |
flush += composedText.toString(); |
|
754 |
} |
|
755 |
||
756 |
if (!flush.equals("")) { |
|
757 |
AttributedString attrstr = new AttributedString(flush); |
|
758 |
postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, |
|
759 |
attrstr.getIterator(), |
|
760 |
flush.length(), |
|
761 |
null, |
|
762 |
null, |
|
763 |
EventQueue.getMostRecentEventTime()); |
|
764 |
composedText = null; |
|
765 |
committedText = null; |
|
766 |
} |
|
767 |
} |
|
768 |
||
769 |
/* |
|
770 |
* Subclasses should override disposeImpl() instead of dispose(). Client |
|
771 |
* code should always invoke dispose(), never disposeImpl(). |
|
772 |
*/ |
|
773 |
protected synchronized void disposeImpl() { |
|
774 |
disposeXIC(); |
|
775 |
awtLock(); |
|
776 |
composedText = null; |
|
777 |
committedText = null; |
|
778 |
rawFeedbacks = null; |
|
779 |
awtUnlock(); |
|
780 |
awtFocussedComponent = null; |
|
781 |
lastXICFocussedComponent = null; |
|
782 |
} |
|
783 |
||
784 |
/** |
|
785 |
* Frees all X Window resources associated with this object. |
|
786 |
* |
|
787 |
* @see java.awt.im.spi.InputMethod#dispose |
|
788 |
*/ |
|
789 |
public final void dispose() { |
|
790 |
boolean call_disposeImpl = false; |
|
791 |
||
792 |
if (!disposed) { |
|
793 |
synchronized (this) { |
|
794 |
if (!disposed) { |
|
795 |
disposed = call_disposeImpl = true; |
|
796 |
} |
|
797 |
} |
|
798 |
} |
|
799 |
||
800 |
if (call_disposeImpl) { |
|
801 |
disposeImpl(); |
|
802 |
} |
|
803 |
} |
|
804 |
||
805 |
/** |
|
806 |
* Returns null. |
|
807 |
* |
|
808 |
* @see java.awt.im.spi.InputMethod#getControlObject |
|
809 |
*/ |
|
810 |
public Object getControlObject() { |
|
811 |
return null; |
|
812 |
} |
|
813 |
||
814 |
/** |
|
815 |
* @see java.awt.im.spi.InputMethod#removeNotify |
|
816 |
*/ |
|
817 |
public synchronized void removeNotify() { |
|
818 |
dispose(); |
|
819 |
} |
|
820 |
||
821 |
/** |
|
822 |
* @see java.awt.im.spi.InputMethod#setCompositionEnabled(boolean) |
|
823 |
*/ |
|
824 |
public void setCompositionEnabled(boolean enable) { |
|
825 |
/* If the composition state is successfully changed, set |
|
826 |
the savedCompositionState to 'enable'. Otherwise, simply |
|
827 |
return. |
|
828 |
setCompositionEnabledNative may throw UnsupportedOperationException. |
|
829 |
Don't try to catch it since the method may be called by clients. |
|
830 |
Use package private mthod 'resetCompositionState' if you want the |
|
831 |
exception to be caught. |
|
832 |
*/ |
|
833 |
if (setCompositionEnabledNative(enable)) { |
|
834 |
savedCompositionState = enable; |
|
835 |
} |
|
836 |
} |
|
837 |
||
838 |
/** |
|
839 |
* @see java.awt.im.spi.InputMethod#isCompositionEnabled |
|
840 |
*/ |
|
841 |
public boolean isCompositionEnabled() { |
|
842 |
/* isCompositionEnabledNative may throw UnsupportedOperationException. |
|
843 |
Don't try to catch it since this method may be called by clients. |
|
844 |
Use package private method 'getCompositionState' if you want the |
|
845 |
exception to be caught. |
|
846 |
*/ |
|
847 |
return isCompositionEnabledNative(); |
|
848 |
} |
|
849 |
||
850 |
/** |
|
851 |
* Ends any input composition that may currently be going on in this |
|
852 |
* context. Depending on the platform and possibly user preferences, |
|
853 |
* this may commit or delete uncommitted text. Any changes to the text |
|
854 |
* are communicated to the active component using an input method event. |
|
855 |
* |
|
856 |
* <p> |
|
857 |
* A text editing component may call this in a variety of situations, |
|
858 |
* for example, when the user moves the insertion point within the text |
|
859 |
* (but outside the composed text), or when the component's text is |
|
860 |
* saved to a file or copied to the clipboard. |
|
861 |
* |
|
862 |
*/ |
|
863 |
public void endComposition() { |
|
864 |
if (disposed) { |
|
865 |
return; |
|
866 |
} |
|
867 |
||
868 |
/* Before calling resetXIC, record the current composition mode |
|
869 |
so that it can be restored later. */ |
|
870 |
savedCompositionState = getCompositionState(); |
|
871 |
boolean active = haveActiveClient(); |
|
872 |
if (active && composedText == null && committedText == null){ |
|
873 |
needResetXIC = true; |
|
15638 | 874 |
needResetXICClient = new WeakReference<>(getClientComponent()); |
2 | 875 |
return; |
876 |
} |
|
877 |
||
878 |
String text = resetXIC(); |
|
879 |
/* needResetXIC is only set to true for active client. So passive |
|
880 |
client should not reset the flag to false. */ |
|
881 |
if (active) { |
|
882 |
needResetXIC = false; |
|
883 |
} |
|
884 |
||
885 |
// Remove any existing composed text by posting an InputMethodEvent |
|
886 |
// with null composed text. It would be desirable to wait for a |
|
887 |
// dispatchComposedText call from X input method engine, but some |
|
888 |
// input method does not conform to the XIM specification and does |
|
889 |
// not call the preedit callback to erase preedit text on calling |
|
890 |
// XmbResetIC. To work around this problem, do it here by ourselves. |
|
891 |
awtLock(); |
|
892 |
composedText = null; |
|
893 |
postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, |
|
894 |
null, |
|
895 |
0, |
|
896 |
null, |
|
897 |
null); |
|
898 |
||
899 |
if (text != null && text.length() > 0) { |
|
900 |
dispatchCommittedText(text); |
|
901 |
} |
|
902 |
awtUnlock(); |
|
903 |
||
904 |
// Restore the preedit state if it was enabled |
|
905 |
if (savedCompositionState) { |
|
906 |
resetCompositionState(); |
|
907 |
} |
|
908 |
} |
|
909 |
||
910 |
/** |
|
911 |
* Returns a string with information about the current input method server, or null. |
|
912 |
* On both Linux & SunOS, the value of environment variable XMODIFIERS is |
|
913 |
* returned if set. Otherwise, on SunOS, $HOME/.dtprofile will be parsed |
|
914 |
* to find out the language service engine (atok or wnn) since there is |
|
915 |
* no API in Xlib which returns the information of native |
|
916 |
* IM server or language service and we want to try our best to return as much |
|
917 |
* information as possible. |
|
918 |
* |
|
919 |
* Note: This method could return null on Linux if XMODIFIERS is not set properly or |
|
920 |
* if any IOException is thrown. |
|
921 |
* See man page of XSetLocaleModifiers(3X11) for the usgae of XMODIFIERS, |
|
922 |
* atok12setup(1) and wnn6setup(1) for the information written to |
|
923 |
* $HOME/.dtprofile when you run these two commands. |
|
924 |
* |
|
925 |
*/ |
|
926 |
public String getNativeInputMethodInfo() { |
|
927 |
String xmodifiers = System.getenv("XMODIFIERS"); |
|
928 |
String imInfo = null; |
|
929 |
||
930 |
// If XMODIFIERS is set, return the value |
|
931 |
if (xmodifiers != null) { |
|
932 |
int imIndex = xmodifiers.indexOf("@im="); |
|
933 |
if (imIndex != -1) { |
|
934 |
imInfo = xmodifiers.substring(imIndex + 4); |
|
935 |
} |
|
936 |
} else if (System.getProperty("os.name").startsWith("SunOS")) { |
|
937 |
File dtprofile = new File(System.getProperty("user.home") + |
|
938 |
"/.dtprofile"); |
|
939 |
String languageEngineInfo = null; |
|
940 |
try { |
|
941 |
BufferedReader br = new BufferedReader(new FileReader(dtprofile)); |
|
942 |
String line = null; |
|
943 |
||
944 |
while ( languageEngineInfo == null && (line = br.readLine()) != null) { |
|
945 |
if (line.contains("atok") || line.contains("wnn")) { |
|
946 |
StringTokenizer tokens = new StringTokenizer(line); |
|
947 |
while (tokens.hasMoreTokens()) { |
|
948 |
String token = tokens.nextToken(); |
|
949 |
if (Pattern.matches("atok.*setup", token) || |
|
950 |
Pattern.matches("wnn.*setup", token)){ |
|
951 |
languageEngineInfo = token.substring(0, token.indexOf("setup")); |
|
952 |
break; |
|
953 |
} |
|
954 |
} |
|
955 |
} |
|
956 |
} |
|
957 |
||
958 |
br.close(); |
|
959 |
} catch(IOException ioex) { |
|
960 |
// Since this method is provided for internal testing only, |
|
961 |
// we dump the stack trace for the ease of debugging. |
|
962 |
ioex.printStackTrace(); |
|
963 |
} |
|
964 |
||
965 |
imInfo = "htt " + languageEngineInfo; |
|
966 |
} |
|
967 |
||
968 |
return imInfo; |
|
969 |
} |
|
970 |
||
971 |
||
972 |
/** |
|
973 |
* Performs mapping from an XIM visible feedback value to Java IM highlight. |
|
974 |
* @return Java input method highlight |
|
975 |
*/ |
|
976 |
private InputMethodHighlight convertVisualFeedbackToHighlight(int feedback) { |
|
977 |
InputMethodHighlight highlight; |
|
978 |
||
979 |
switch (feedback) { |
|
980 |
case XIMUnderline: |
|
981 |
highlight = InputMethodHighlight.UNSELECTED_CONVERTED_TEXT_HIGHLIGHT; |
|
982 |
break; |
|
983 |
case XIMReverse: |
|
984 |
highlight = InputMethodHighlight.SELECTED_CONVERTED_TEXT_HIGHLIGHT; |
|
985 |
break; |
|
986 |
case XIMHighlight: |
|
987 |
highlight = InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT; |
|
988 |
break; |
|
989 |
case XIMPrimary: |
|
990 |
highlight = InputMethodHighlight.UNSELECTED_CONVERTED_TEXT_HIGHLIGHT; |
|
991 |
break; |
|
992 |
case XIMSecondary: |
|
993 |
highlight = InputMethodHighlight.SELECTED_CONVERTED_TEXT_HIGHLIGHT; |
|
994 |
break; |
|
995 |
case XIMTertiary: |
|
996 |
highlight = InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT; |
|
997 |
break; |
|
998 |
default: |
|
999 |
highlight = InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT; |
|
1000 |
break; |
|
1001 |
} |
|
1002 |
return highlight; |
|
1003 |
} |
|
1004 |
||
1005 |
// initial capacity size for string buffer, etc. |
|
1006 |
private static final int INITIAL_SIZE = 64; |
|
1007 |
||
1008 |
/** |
|
1009 |
* IntBuffer is an inner class that manipulates an int array and |
|
1010 |
* provides UNIX file io stream-like programming interfaces to |
|
1011 |
* access it. (An alternative would be to use ArrayList which may |
|
1012 |
* be too expensive for the work.) |
|
1013 |
*/ |
|
1014 |
private final class IntBuffer { |
|
1015 |
private int[] intArray; |
|
1016 |
private int size; |
|
1017 |
private int index; |
|
1018 |
||
1019 |
IntBuffer(int initialCapacity) { |
|
1020 |
intArray = new int[initialCapacity]; |
|
1021 |
size = 0; |
|
1022 |
index = 0; |
|
1023 |
} |
|
1024 |
||
1025 |
void insert(int offset, int[] values) { |
|
1026 |
int newSize = size + values.length; |
|
1027 |
if (intArray.length < newSize) { |
|
1028 |
int[] newIntArray = new int[newSize * 2]; |
|
1029 |
System.arraycopy(intArray, 0, newIntArray, 0, size); |
|
1030 |
intArray = newIntArray; |
|
1031 |
} |
|
1032 |
System.arraycopy(intArray, offset, intArray, offset+values.length, |
|
1033 |
size - offset); |
|
1034 |
System.arraycopy(values, 0, intArray, offset, values.length); |
|
1035 |
size += values.length; |
|
1036 |
if (index > offset) |
|
1037 |
index = offset; |
|
1038 |
} |
|
1039 |
||
1040 |
void remove(int offset, int length) { |
|
1041 |
if (offset + length != size) |
|
1042 |
System.arraycopy(intArray, offset+length, intArray, offset, |
|
1043 |
size - offset - length); |
|
1044 |
size -= length; |
|
1045 |
if (index > offset) |
|
1046 |
index = offset; |
|
1047 |
} |
|
1048 |
||
1049 |
void replace(int offset, int[] values) { |
|
1050 |
System.arraycopy(values, 0, intArray, offset, values.length); |
|
1051 |
} |
|
1052 |
||
1053 |
void removeAll() { |
|
1054 |
size = 0; |
|
1055 |
index = 0; |
|
1056 |
} |
|
1057 |
||
1058 |
void rewind() { |
|
1059 |
index = 0; |
|
1060 |
} |
|
1061 |
||
1062 |
int getNext() { |
|
1063 |
if (index == size) |
|
1064 |
return -1; |
|
1065 |
return intArray[index++]; |
|
1066 |
} |
|
1067 |
||
1068 |
void unget() { |
|
1069 |
if (index != 0) |
|
1070 |
index--; |
|
1071 |
} |
|
1072 |
||
1073 |
int getOffset() { |
|
1074 |
return index; |
|
1075 |
} |
|
1076 |
||
1077 |
public String toString() { |
|
1078 |
StringBuffer s = new StringBuffer(); |
|
1079 |
for (int i = 0; i < size;) { |
|
1080 |
s.append(intArray[i++]); |
|
1081 |
if (i < size) |
|
1082 |
s.append(","); |
|
1083 |
} |
|
1084 |
return s.toString(); |
|
1085 |
} |
|
1086 |
} |
|
1087 |
||
1088 |
/* |
|
1089 |
* Native methods |
|
1090 |
*/ |
|
30938
35ae5c70d60e
8030087: Avoid public native methods in sun.awt packages
serb
parents:
25859
diff
changeset
|
1091 |
private native String resetXIC(); |
2 | 1092 |
private native void disposeXIC(); |
1093 |
private native boolean setCompositionEnabledNative(boolean enable); |
|
1094 |
private native boolean isCompositionEnabledNative(); |
|
1095 |
private native void turnoffStatusWindow(); |
|
1096 |
} |