author | ohair |
Tue, 25 May 2010 15:58:33 -0700 | |
changeset 5506 | 202f599c92aa |
parent 3938 | ef327bd847c0 |
child 11126 | 00a6b63e7ba4 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
5506 | 2 |
* Copyright (c) 1997, 2008, 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.im; |
|
27 |
||
28 |
import java.awt.AWTEvent; |
|
29 |
import java.awt.AWTKeyStroke; |
|
30 |
import java.awt.Component; |
|
31 |
import java.awt.EventQueue; |
|
32 |
import java.awt.Frame; |
|
33 |
import java.awt.Rectangle; |
|
34 |
import java.awt.Toolkit; |
|
35 |
import java.awt.Window; |
|
36 |
import java.awt.event.ComponentEvent; |
|
37 |
import java.awt.event.ComponentListener; |
|
38 |
import java.awt.event.FocusEvent; |
|
39 |
import java.awt.event.InputEvent; |
|
40 |
import java.awt.event.InputMethodEvent; |
|
41 |
import java.awt.event.KeyEvent; |
|
42 |
import java.awt.event.WindowEvent; |
|
43 |
import java.awt.event.WindowListener; |
|
44 |
import java.awt.im.InputMethodRequests; |
|
45 |
import java.awt.im.spi.InputMethod; |
|
46 |
import java.lang.Character.Subset; |
|
47 |
import java.security.AccessController; |
|
48 |
import java.security.PrivilegedAction; |
|
49 |
import java.text.MessageFormat; |
|
50 |
import java.util.HashMap; |
|
51 |
import java.util.Iterator; |
|
52 |
import java.util.Locale; |
|
53 |
import java.util.prefs.BackingStoreException; |
|
54 |
import java.util.prefs.Preferences; |
|
3938
ef327bd847c0
6879044: Eliminate the dependency on logging from the AWT/2D/Swing classes
mchung
parents:
1311
diff
changeset
|
55 |
import sun.util.logging.PlatformLogger; |
2 | 56 |
import sun.awt.SunToolkit; |
57 |
||
58 |
/** |
|
59 |
* This InputContext class contains parts of the implementation of |
|
60 |
* java.text.im.InputContext. These parts have been moved |
|
61 |
* here to avoid exposing protected members that are needed by the |
|
62 |
* subclass InputMethodContext. |
|
63 |
* |
|
64 |
* @see java.awt.im.InputContext |
|
65 |
* @author JavaSoft Asia/Pacific |
|
66 |
*/ |
|
67 |
||
68 |
public class InputContext extends java.awt.im.InputContext |
|
69 |
implements ComponentListener, WindowListener { |
|
3938
ef327bd847c0
6879044: Eliminate the dependency on logging from the AWT/2D/Swing classes
mchung
parents:
1311
diff
changeset
|
70 |
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.im.InputContext"); |
2 | 71 |
// The current input method is represented by two objects: |
72 |
// a locator is used to keep information about the selected |
|
73 |
// input method and locale until we actually need a real input |
|
74 |
// method; only then the input method itself is created. |
|
75 |
// Once there is an input method, the input method's locale |
|
76 |
// takes precedence over locale information in the locator. |
|
77 |
private InputMethodLocator inputMethodLocator; |
|
78 |
private InputMethod inputMethod; |
|
79 |
private boolean inputMethodCreationFailed; |
|
80 |
||
81 |
// holding bin for previously used input method instances, but not the current one |
|
82 |
private HashMap usedInputMethods; |
|
83 |
||
84 |
// the current client component is kept until the user focusses on a different |
|
85 |
// client component served by the same input context. When that happens, we call |
|
86 |
// endComposition so that text doesn't jump from one component to another. |
|
87 |
private Component currentClientComponent; |
|
88 |
private Component awtFocussedComponent; |
|
89 |
private boolean isInputMethodActive; |
|
90 |
private Subset[] characterSubsets = null; |
|
91 |
||
92 |
// true if composition area has been set to invisible when focus was lost |
|
93 |
private boolean compositionAreaHidden = false; |
|
94 |
||
95 |
// The input context for whose input method we may have to call hideWindows |
|
96 |
private static InputContext inputMethodWindowContext; |
|
97 |
||
98 |
// Previously active input method to decide whether we need to call |
|
99 |
// InputMethodAdapter.stopListening() on activateInputMethod() |
|
100 |
private static InputMethod previousInputMethod = null; |
|
101 |
||
102 |
// true if the current input method requires client window change notification |
|
103 |
private boolean clientWindowNotificationEnabled = false; |
|
104 |
// client window to which this input context is listening |
|
105 |
private Window clientWindowListened; |
|
106 |
// cache location notification |
|
107 |
private Rectangle clientWindowLocation = null; |
|
108 |
// holding the state of clientWindowNotificationEnabled of only non-current input methods |
|
109 |
private HashMap perInputMethodState; |
|
110 |
||
111 |
// Input Method selection hot key stuff |
|
112 |
private static AWTKeyStroke inputMethodSelectionKey; |
|
113 |
private static boolean inputMethodSelectionKeyInitialized = false; |
|
114 |
private static final String inputMethodSelectionKeyPath = "/java/awt/im/selectionKey"; |
|
115 |
private static final String inputMethodSelectionKeyCodeName = "keyCode"; |
|
116 |
private static final String inputMethodSelectionKeyModifiersName = "modifiers"; |
|
117 |
||
118 |
/** |
|
119 |
* Constructs an InputContext. |
|
120 |
*/ |
|
121 |
protected InputContext() { |
|
122 |
InputMethodManager imm = InputMethodManager.getInstance(); |
|
123 |
synchronized (InputContext.class) { |
|
124 |
if (!inputMethodSelectionKeyInitialized) { |
|
125 |
inputMethodSelectionKeyInitialized = true; |
|
126 |
if (imm.hasMultipleInputMethods()) { |
|
127 |
initializeInputMethodSelectionKey(); |
|
128 |
} |
|
129 |
} |
|
130 |
} |
|
131 |
selectInputMethod(imm.getDefaultKeyboardLocale()); |
|
132 |
} |
|
133 |
||
134 |
/** |
|
135 |
* @see java.awt.im.InputContext#selectInputMethod |
|
136 |
* @exception NullPointerException when the locale is null. |
|
137 |
*/ |
|
138 |
public synchronized boolean selectInputMethod(Locale locale) { |
|
139 |
if (locale == null) { |
|
140 |
throw new NullPointerException(); |
|
141 |
} |
|
142 |
||
143 |
// see whether the current input method supports the locale |
|
144 |
if (inputMethod != null) { |
|
145 |
if (inputMethod.setLocale(locale)) { |
|
146 |
return true; |
|
147 |
} |
|
148 |
} else if (inputMethodLocator != null) { |
|
149 |
// This is not 100% correct, since the input method |
|
150 |
// may support the locale without advertising it. |
|
151 |
// But before we try instantiations and setLocale, |
|
152 |
// we look for an input method that's more confident. |
|
153 |
if (inputMethodLocator.isLocaleAvailable(locale)) { |
|
154 |
inputMethodLocator = inputMethodLocator.deriveLocator(locale); |
|
155 |
return true; |
|
156 |
} |
|
157 |
} |
|
158 |
||
159 |
// see whether there's some other input method that supports the locale |
|
160 |
InputMethodLocator newLocator = InputMethodManager.getInstance().findInputMethod(locale); |
|
161 |
if (newLocator != null) { |
|
162 |
changeInputMethod(newLocator); |
|
163 |
return true; |
|
164 |
} |
|
165 |
||
166 |
// make one last desperate effort with the current input method |
|
167 |
// ??? is this good? This is pretty high cost for something that's likely to fail. |
|
168 |
if (inputMethod == null && inputMethodLocator != null) { |
|
169 |
inputMethod = getInputMethod(); |
|
170 |
if (inputMethod != null) { |
|
171 |
return inputMethod.setLocale(locale); |
|
172 |
} |
|
173 |
} |
|
174 |
return false; |
|
175 |
} |
|
176 |
||
177 |
/** |
|
178 |
* @see java.awt.im.InputContext#getLocale |
|
179 |
*/ |
|
180 |
public Locale getLocale() { |
|
181 |
if (inputMethod != null) { |
|
182 |
return inputMethod.getLocale(); |
|
183 |
} else if (inputMethodLocator != null) { |
|
184 |
return inputMethodLocator.getLocale(); |
|
185 |
} else { |
|
186 |
return null; |
|
187 |
} |
|
188 |
} |
|
189 |
||
190 |
/** |
|
191 |
* @see java.awt.im.InputContext#setCharacterSubsets |
|
192 |
*/ |
|
193 |
public void setCharacterSubsets(Subset[] subsets) { |
|
194 |
if (subsets == null) { |
|
195 |
characterSubsets = null; |
|
196 |
} else { |
|
197 |
characterSubsets = new Subset[subsets.length]; |
|
198 |
System.arraycopy(subsets, 0, |
|
199 |
characterSubsets, 0, characterSubsets.length); |
|
200 |
} |
|
201 |
if (inputMethod != null) { |
|
202 |
inputMethod.setCharacterSubsets(subsets); |
|
203 |
} |
|
204 |
} |
|
205 |
||
206 |
/** |
|
207 |
* @see java.awt.im.InputContext#reconvert |
|
208 |
* @since 1.3 |
|
209 |
* @exception UnsupportedOperationException when input method is null |
|
210 |
*/ |
|
211 |
public synchronized void reconvert() { |
|
212 |
InputMethod inputMethod = getInputMethod(); |
|
213 |
if (inputMethod == null) { |
|
214 |
throw new UnsupportedOperationException(); |
|
215 |
} |
|
216 |
inputMethod.reconvert(); |
|
217 |
} |
|
218 |
||
219 |
/** |
|
220 |
* @see java.awt.im.InputContext#dispatchEvent |
|
221 |
*/ |
|
222 |
public void dispatchEvent(AWTEvent event) { |
|
223 |
||
224 |
if (event instanceof InputMethodEvent) { |
|
225 |
return; |
|
226 |
} |
|
227 |
||
228 |
// Ignore focus events that relate to the InputMethodWindow of this context. |
|
229 |
// This is a workaround. Should be removed after 4452384 is fixed. |
|
230 |
if (event instanceof FocusEvent) { |
|
231 |
Component opposite = ((FocusEvent)event).getOppositeComponent(); |
|
232 |
if ((opposite != null) && |
|
233 |
(getComponentWindow(opposite) instanceof InputMethodWindow) && |
|
234 |
(opposite.getInputContext() == this)) { |
|
235 |
return; |
|
236 |
} |
|
237 |
} |
|
238 |
||
239 |
InputMethod inputMethod = getInputMethod(); |
|
240 |
int id = event.getID(); |
|
241 |
||
242 |
switch (id) { |
|
243 |
case FocusEvent.FOCUS_GAINED: |
|
244 |
focusGained((Component) event.getSource()); |
|
245 |
break; |
|
246 |
||
247 |
case FocusEvent.FOCUS_LOST: |
|
248 |
focusLost((Component) event.getSource(), ((FocusEvent) event).isTemporary()); |
|
249 |
break; |
|
250 |
||
251 |
case KeyEvent.KEY_PRESSED: |
|
252 |
if (checkInputMethodSelectionKey((KeyEvent)event)) { |
|
253 |
// pop up the input method selection menu |
|
254 |
InputMethodManager.getInstance().notifyChangeRequestByHotKey((Component)event.getSource()); |
|
255 |
break; |
|
256 |
} |
|
257 |
||
258 |
// fall through |
|
259 |
||
260 |
default: |
|
261 |
if ((inputMethod != null) && (event instanceof InputEvent)) { |
|
262 |
inputMethod.dispatchEvent(event); |
|
263 |
} |
|
264 |
} |
|
265 |
} |
|
266 |
||
267 |
/** |
|
268 |
* Handles focus gained events for any component that's using |
|
269 |
* this input context. |
|
270 |
* These events are generated by AWT when the keyboard focus |
|
271 |
* moves to a component. |
|
272 |
* Besides actual client components, the source components |
|
273 |
* may also be the composition area or any component in an |
|
274 |
* input method window. |
|
275 |
* <p> |
|
276 |
* When handling the focus event for a client component, this |
|
277 |
* method checks whether the input context was previously |
|
278 |
* active for a different client component, and if so, calls |
|
279 |
* endComposition for the previous client component. |
|
280 |
* |
|
281 |
* @param source the component gaining the focus |
|
282 |
*/ |
|
283 |
private void focusGained(Component source) { |
|
284 |
||
285 |
/* |
|
286 |
* NOTE: When a Container is removing its Component which |
|
287 |
* invokes this.removeNotify(), the Container has the global |
|
288 |
* Component lock. It is possible to happen that an |
|
289 |
* application thread is calling this.removeNotify() while an |
|
290 |
* AWT event queue thread is dispatching a focus event via |
|
291 |
* this.dispatchEvent(). If an input method uses AWT |
|
292 |
* components (e.g., IIIMP status window), it causes deadlock, |
|
293 |
* for example, Component.show()/hide() in this situation |
|
294 |
* because hide/show tried to obtain the lock. Therefore, |
|
295 |
* it's necessary to obtain the global Component lock before |
|
296 |
* activating or deactivating an input method. |
|
297 |
*/ |
|
298 |
synchronized (source.getTreeLock()) { |
|
299 |
synchronized (this) { |
|
1311
2b1552286d23
6607310: InputContext may cause loading of swing classes even for non-Swing applets
peytoia
parents:
715
diff
changeset
|
300 |
if ("sun.awt.im.CompositionArea".equals(source.getClass().getName())) { |
2 | 301 |
// no special handling for this one |
302 |
} else if (getComponentWindow(source) instanceof InputMethodWindow) { |
|
303 |
// no special handling for this one either |
|
304 |
} else { |
|
305 |
if (!source.isDisplayable()) { |
|
306 |
// Component is being disposed |
|
307 |
return; |
|
308 |
} |
|
309 |
||
310 |
// Focus went to a real client component. |
|
311 |
// Check whether we're switching between client components |
|
312 |
// that share an input context. We can't do that earlier |
|
313 |
// than here because we don't want to end composition |
|
314 |
// until we really know we're switching to a different component |
|
315 |
if (inputMethod != null) { |
|
316 |
if (currentClientComponent != null && currentClientComponent != source) { |
|
317 |
if (!isInputMethodActive) { |
|
318 |
activateInputMethod(false); |
|
319 |
} |
|
320 |
endComposition(); |
|
321 |
deactivateInputMethod(false); |
|
322 |
} |
|
323 |
} |
|
324 |
||
325 |
currentClientComponent = source; |
|
326 |
} |
|
327 |
||
328 |
awtFocussedComponent = source; |
|
329 |
if (inputMethod instanceof InputMethodAdapter) { |
|
330 |
((InputMethodAdapter) inputMethod).setAWTFocussedComponent(source); |
|
331 |
} |
|
332 |
||
333 |
// it's possible that the input method is still active because |
|
334 |
// we suppressed a deactivate cause by an input method window |
|
335 |
// coming up |
|
336 |
if (!isInputMethodActive) { |
|
337 |
activateInputMethod(true); |
|
338 |
} |
|
339 |
||
340 |
||
341 |
// If the client component is an active client with the below-the-spot |
|
342 |
// input style, then make the composition window undecorated without a title bar. |
|
343 |
InputMethodContext inputContext = ((InputMethodContext)this); |
|
344 |
if (!inputContext.isCompositionAreaVisible()) { |
|
345 |
InputMethodRequests req = source.getInputMethodRequests(); |
|
346 |
if (req != null && inputContext.useBelowTheSpotInput()) { |
|
347 |
inputContext.setCompositionAreaUndecorated(true); |
|
348 |
} else { |
|
349 |
inputContext.setCompositionAreaUndecorated(false); |
|
350 |
} |
|
351 |
} |
|
352 |
// restores the composition area if it was set to invisible |
|
353 |
// when focus got lost |
|
354 |
if (compositionAreaHidden == true) { |
|
355 |
((InputMethodContext)this).setCompositionAreaVisible(true); |
|
356 |
compositionAreaHidden = false; |
|
357 |
} |
|
358 |
} |
|
359 |
} |
|
360 |
} |
|
361 |
||
362 |
/** |
|
363 |
* Activates the current input method of this input context, and grabs |
|
364 |
* the composition area for use by this input context. |
|
365 |
* If updateCompositionArea is true, the text in the composition area |
|
366 |
* is updated (set to false if the text is going to change immediately |
|
367 |
* to avoid screen flicker). |
|
368 |
*/ |
|
369 |
private void activateInputMethod(boolean updateCompositionArea) { |
|
370 |
// call hideWindows() if this input context uses a different |
|
371 |
// input method than the previously activated one |
|
372 |
if (inputMethodWindowContext != null && inputMethodWindowContext != this && |
|
373 |
inputMethodWindowContext.inputMethodLocator != null && |
|
374 |
!inputMethodWindowContext.inputMethodLocator.sameInputMethod(inputMethodLocator) && |
|
375 |
inputMethodWindowContext.inputMethod != null) { |
|
376 |
inputMethodWindowContext.inputMethod.hideWindows(); |
|
377 |
} |
|
378 |
inputMethodWindowContext = this; |
|
379 |
||
380 |
if (inputMethod != null) { |
|
381 |
if (previousInputMethod != inputMethod && |
|
382 |
previousInputMethod instanceof InputMethodAdapter) { |
|
383 |
// let the host adapter pass through the input events for the |
|
384 |
// new input method |
|
385 |
((InputMethodAdapter) previousInputMethod).stopListening(); |
|
386 |
} |
|
387 |
previousInputMethod = null; |
|
388 |
||
3938
ef327bd847c0
6879044: Eliminate the dependency on logging from the AWT/2D/Swing classes
mchung
parents:
1311
diff
changeset
|
389 |
if (log.isLoggable(PlatformLogger.FINE)) log.fine("Current client component " + currentClientComponent); |
2 | 390 |
if (inputMethod instanceof InputMethodAdapter) { |
391 |
((InputMethodAdapter) inputMethod).setClientComponent(currentClientComponent); |
|
392 |
} |
|
393 |
inputMethod.activate(); |
|
394 |
isInputMethodActive = true; |
|
395 |
||
396 |
if (perInputMethodState != null) { |
|
397 |
Boolean state = (Boolean) perInputMethodState.remove(inputMethod); |
|
398 |
if (state != null) { |
|
399 |
clientWindowNotificationEnabled = state.booleanValue(); |
|
400 |
} |
|
401 |
} |
|
402 |
if (clientWindowNotificationEnabled) { |
|
403 |
if (!addedClientWindowListeners()) { |
|
404 |
addClientWindowListeners(); |
|
405 |
} |
|
406 |
synchronized(this) { |
|
407 |
if (clientWindowListened != null) { |
|
408 |
notifyClientWindowChange(clientWindowListened); |
|
409 |
} |
|
410 |
} |
|
411 |
} else { |
|
412 |
if (addedClientWindowListeners()) { |
|
413 |
removeClientWindowListeners(); |
|
414 |
} |
|
415 |
} |
|
416 |
} |
|
417 |
InputMethodManager.getInstance().setInputContext(this); |
|
418 |
||
419 |
((InputMethodContext) this).grabCompositionArea(updateCompositionArea); |
|
420 |
} |
|
421 |
||
422 |
static Window getComponentWindow(Component component) { |
|
423 |
while (true) { |
|
424 |
if (component == null) { |
|
425 |
return null; |
|
426 |
} else if (component instanceof Window) { |
|
427 |
return (Window) component; |
|
428 |
} else { |
|
429 |
component = component.getParent(); |
|
430 |
} |
|
431 |
} |
|
432 |
} |
|
433 |
||
434 |
/** |
|
435 |
* Handles focus lost events for any component that's using |
|
436 |
* this input context. |
|
437 |
* These events are generated by AWT when the keyboard focus |
|
438 |
* moves away from a component. |
|
439 |
* Besides actual client components, the source components |
|
440 |
* may also be the composition area or any component in an |
|
441 |
* input method window. |
|
442 |
* |
|
443 |
* @param source the component losing the focus |
|
444 |
* @isTemporary whether the focus change is temporary |
|
445 |
*/ |
|
446 |
private void focusLost(Component source, boolean isTemporary) { |
|
447 |
||
448 |
// see the note on synchronization in focusGained |
|
449 |
synchronized (source.getTreeLock()) { |
|
450 |
synchronized (this) { |
|
451 |
||
452 |
// We need to suppress deactivation if removeNotify has been called earlier. |
|
453 |
// This is indicated by isInputMethodActive == false. |
|
454 |
if (isInputMethodActive) { |
|
455 |
deactivateInputMethod(isTemporary); |
|
456 |
} |
|
457 |
||
458 |
awtFocussedComponent = null; |
|
459 |
if (inputMethod instanceof InputMethodAdapter) { |
|
460 |
((InputMethodAdapter) inputMethod).setAWTFocussedComponent(null); |
|
461 |
} |
|
462 |
||
463 |
// hides the composition area if currently it is visible |
|
464 |
InputMethodContext inputContext = ((InputMethodContext)this); |
|
465 |
if (inputContext.isCompositionAreaVisible()) { |
|
466 |
inputContext.setCompositionAreaVisible(false); |
|
467 |
compositionAreaHidden = true; |
|
468 |
} |
|
469 |
} |
|
470 |
} |
|
471 |
} |
|
472 |
||
473 |
/** |
|
474 |
* Checks the key event is the input method selection key or not. |
|
475 |
*/ |
|
476 |
private boolean checkInputMethodSelectionKey(KeyEvent event) { |
|
477 |
if (inputMethodSelectionKey != null) { |
|
478 |
AWTKeyStroke aKeyStroke = AWTKeyStroke.getAWTKeyStrokeForEvent(event); |
|
479 |
return inputMethodSelectionKey.equals(aKeyStroke); |
|
480 |
} else { |
|
481 |
return false; |
|
482 |
} |
|
483 |
} |
|
484 |
||
485 |
private void deactivateInputMethod(boolean isTemporary) { |
|
486 |
InputMethodManager.getInstance().setInputContext(null); |
|
487 |
if (inputMethod != null) { |
|
488 |
isInputMethodActive = false; |
|
489 |
inputMethod.deactivate(isTemporary); |
|
490 |
previousInputMethod = inputMethod; |
|
491 |
} |
|
492 |
} |
|
493 |
||
494 |
/** |
|
495 |
* Switches from the current input method to the one described by newLocator. |
|
496 |
* The current input method, if any, is asked to end composition, deactivated, |
|
497 |
* and saved for future use. The newLocator is made the current locator. If |
|
498 |
* the input context is active, an input method instance for the new locator |
|
499 |
* is obtained; otherwise this is deferred until required. |
|
500 |
*/ |
|
501 |
synchronized void changeInputMethod(InputMethodLocator newLocator) { |
|
502 |
// If we don't have a locator yet, this must be a new input context. |
|
503 |
// If we created a new input method here, we might get into an |
|
504 |
// infinite loop: create input method -> create some input method window -> |
|
505 |
// create new input context -> add input context to input method manager's context list -> |
|
506 |
// call changeInputMethod on it. |
|
507 |
// So, just record the locator. dispatchEvent will create the input method when needed. |
|
508 |
if (inputMethodLocator == null) { |
|
509 |
inputMethodLocator = newLocator; |
|
510 |
inputMethodCreationFailed = false; |
|
511 |
return; |
|
512 |
} |
|
513 |
||
514 |
// If the same input method is specified, just keep it. |
|
515 |
// Adjust the locale if necessary. |
|
516 |
if (inputMethodLocator.sameInputMethod(newLocator)) { |
|
517 |
Locale newLocale = newLocator.getLocale(); |
|
518 |
if (newLocale != null && inputMethodLocator.getLocale() != newLocale) { |
|
519 |
if (inputMethod != null) { |
|
520 |
inputMethod.setLocale(newLocale); |
|
521 |
} |
|
522 |
inputMethodLocator = newLocator; |
|
523 |
} |
|
524 |
return; |
|
525 |
} |
|
526 |
||
527 |
// Switch out the old input method |
|
528 |
Locale savedLocale = inputMethodLocator.getLocale(); |
|
529 |
boolean wasInputMethodActive = isInputMethodActive; |
|
530 |
boolean wasCompositionEnabledSupported = false; |
|
531 |
boolean wasCompositionEnabled = false; |
|
532 |
if (inputMethod != null) { |
|
533 |
try { |
|
534 |
wasCompositionEnabled = inputMethod.isCompositionEnabled(); |
|
535 |
wasCompositionEnabledSupported = true; |
|
536 |
} catch (UnsupportedOperationException e) { } |
|
537 |
||
538 |
if (currentClientComponent != null) { |
|
539 |
if (!isInputMethodActive) { |
|
540 |
activateInputMethod(false); |
|
541 |
} |
|
542 |
endComposition(); |
|
543 |
deactivateInputMethod(false); |
|
544 |
if (inputMethod instanceof InputMethodAdapter) { |
|
545 |
((InputMethodAdapter) inputMethod).setClientComponent(null); |
|
546 |
} |
|
547 |
} |
|
548 |
savedLocale = inputMethod.getLocale(); |
|
549 |
||
550 |
// keep the input method instance around for future use |
|
551 |
if (usedInputMethods == null) { |
|
552 |
usedInputMethods = new HashMap(5); |
|
553 |
} |
|
554 |
if (perInputMethodState == null) { |
|
555 |
perInputMethodState = new HashMap(5); |
|
556 |
} |
|
557 |
usedInputMethods.put(inputMethodLocator.deriveLocator(null), inputMethod); |
|
558 |
perInputMethodState.put(inputMethod, |
|
438
2ae294e4518c
6613529: Avoid duplicate object creation within JDK packages
dav
parents:
2
diff
changeset
|
559 |
Boolean.valueOf(clientWindowNotificationEnabled)); |
2 | 560 |
enableClientWindowNotification(inputMethod, false); |
561 |
if (this == inputMethodWindowContext) { |
|
562 |
inputMethod.hideWindows(); |
|
563 |
inputMethodWindowContext = null; |
|
564 |
} |
|
565 |
inputMethodLocator = null; |
|
566 |
inputMethod = null; |
|
567 |
inputMethodCreationFailed = false; |
|
568 |
} |
|
569 |
||
570 |
// Switch in the new input method |
|
571 |
if (newLocator.getLocale() == null && savedLocale != null && |
|
572 |
newLocator.isLocaleAvailable(savedLocale)) { |
|
573 |
newLocator = newLocator.deriveLocator(savedLocale); |
|
574 |
} |
|
575 |
inputMethodLocator = newLocator; |
|
576 |
inputMethodCreationFailed = false; |
|
577 |
||
578 |
// activate the new input method if the old one was active |
|
579 |
if (wasInputMethodActive) { |
|
580 |
inputMethod = getInputMethodInstance(); |
|
581 |
if (inputMethod instanceof InputMethodAdapter) { |
|
582 |
((InputMethodAdapter) inputMethod).setAWTFocussedComponent(awtFocussedComponent); |
|
583 |
} |
|
584 |
activateInputMethod(true); |
|
585 |
} |
|
586 |
||
587 |
// enable/disable composition if the old one supports querying enable/disable |
|
588 |
if (wasCompositionEnabledSupported) { |
|
589 |
inputMethod = getInputMethod(); |
|
590 |
if (inputMethod != null) { |
|
591 |
try { |
|
592 |
inputMethod.setCompositionEnabled(wasCompositionEnabled); |
|
593 |
} catch (UnsupportedOperationException e) { } |
|
594 |
} |
|
595 |
} |
|
596 |
} |
|
597 |
||
598 |
/** |
|
599 |
* Returns the client component. |
|
600 |
*/ |
|
601 |
Component getClientComponent() { |
|
602 |
return currentClientComponent; |
|
603 |
} |
|
604 |
||
605 |
/** |
|
606 |
* @see java.awt.im.InputContext#removeNotify |
|
607 |
* @exception NullPointerException when the component is null. |
|
608 |
*/ |
|
609 |
public synchronized void removeNotify(Component component) { |
|
610 |
if (component == null) { |
|
611 |
throw new NullPointerException(); |
|
612 |
} |
|
613 |
||
614 |
if (inputMethod == null) { |
|
615 |
if (component == currentClientComponent) { |
|
616 |
currentClientComponent = null; |
|
617 |
} |
|
618 |
return; |
|
619 |
} |
|
620 |
||
621 |
// We may or may not get a FOCUS_LOST event for this component, |
|
622 |
// so do the deactivation stuff here too. |
|
623 |
if (component == awtFocussedComponent) { |
|
624 |
focusLost(component, false); |
|
625 |
} |
|
626 |
||
627 |
if (component == currentClientComponent) { |
|
628 |
if (isInputMethodActive) { |
|
629 |
// component wasn't the one that had the focus |
|
630 |
deactivateInputMethod(false); |
|
631 |
} |
|
632 |
inputMethod.removeNotify(); |
|
633 |
if (clientWindowNotificationEnabled && addedClientWindowListeners()) { |
|
634 |
removeClientWindowListeners(); |
|
635 |
} |
|
636 |
currentClientComponent = null; |
|
637 |
if (inputMethod instanceof InputMethodAdapter) { |
|
638 |
((InputMethodAdapter) inputMethod).setClientComponent(null); |
|
639 |
} |
|
640 |
||
641 |
// removeNotify() can be issued from a thread other than the event dispatch |
|
642 |
// thread. In that case, avoid possible deadlock between Component.AWTTreeLock |
|
643 |
// and InputMethodContext.compositionAreaHandlerLock by releasing the composition |
|
644 |
// area on the event dispatch thread. |
|
645 |
if (EventQueue.isDispatchThread()) { |
|
646 |
((InputMethodContext)this).releaseCompositionArea(); |
|
647 |
} else { |
|
648 |
EventQueue.invokeLater(new Runnable() { |
|
649 |
public void run() { |
|
650 |
((InputMethodContext)InputContext.this).releaseCompositionArea(); |
|
651 |
} |
|
652 |
}); |
|
653 |
} |
|
654 |
} |
|
655 |
} |
|
656 |
||
657 |
/** |
|
658 |
* @see java.awt.im.InputContext#dispose |
|
659 |
* @exception IllegalStateException when the currentClientComponent is not null |
|
660 |
*/ |
|
661 |
public synchronized void dispose() { |
|
662 |
if (currentClientComponent != null) { |
|
663 |
throw new IllegalStateException("Can't dispose InputContext while it's active"); |
|
664 |
} |
|
665 |
if (inputMethod != null) { |
|
666 |
if (this == inputMethodWindowContext) { |
|
667 |
inputMethod.hideWindows(); |
|
668 |
inputMethodWindowContext = null; |
|
669 |
} |
|
670 |
if (inputMethod == previousInputMethod) { |
|
671 |
previousInputMethod = null; |
|
672 |
} |
|
673 |
if (clientWindowNotificationEnabled) { |
|
674 |
if (addedClientWindowListeners()) { |
|
675 |
removeClientWindowListeners(); |
|
676 |
} |
|
677 |
clientWindowNotificationEnabled = false; |
|
678 |
} |
|
679 |
inputMethod.dispose(); |
|
680 |
||
681 |
// in case the input method enabled the client window |
|
682 |
// notification in dispose(), which shouldn't happen, it |
|
683 |
// needs to be cleaned up again. |
|
684 |
if (clientWindowNotificationEnabled) { |
|
685 |
enableClientWindowNotification(inputMethod, false); |
|
686 |
} |
|
687 |
||
688 |
inputMethod = null; |
|
689 |
} |
|
690 |
inputMethodLocator = null; |
|
691 |
if (usedInputMethods != null && !usedInputMethods.isEmpty()) { |
|
692 |
Iterator iterator = usedInputMethods.values().iterator(); |
|
693 |
usedInputMethods = null; |
|
694 |
while (iterator.hasNext()) { |
|
695 |
((InputMethod) iterator.next()).dispose(); |
|
696 |
} |
|
697 |
} |
|
698 |
||
699 |
// cleanup client window notification variables |
|
700 |
clientWindowNotificationEnabled = false; |
|
701 |
clientWindowListened = null; |
|
702 |
perInputMethodState = null; |
|
703 |
} |
|
704 |
||
705 |
/** |
|
706 |
* @see java.awt.im.InputContext#getInputMethodControlObject |
|
707 |
*/ |
|
708 |
public synchronized Object getInputMethodControlObject() { |
|
709 |
InputMethod inputMethod = getInputMethod(); |
|
710 |
||
711 |
if (inputMethod != null) { |
|
712 |
return inputMethod.getControlObject(); |
|
713 |
} else { |
|
714 |
return null; |
|
715 |
} |
|
716 |
} |
|
717 |
||
718 |
/** |
|
719 |
* @see java.awt.im.InputContext#setCompositionEnabled(boolean) |
|
720 |
* @exception UnsupportedOperationException when input method is null |
|
721 |
*/ |
|
722 |
public void setCompositionEnabled(boolean enable) { |
|
723 |
InputMethod inputMethod = getInputMethod(); |
|
724 |
||
725 |
if (inputMethod == null) { |
|
726 |
throw new UnsupportedOperationException(); |
|
727 |
} |
|
728 |
inputMethod.setCompositionEnabled(enable); |
|
729 |
} |
|
730 |
||
731 |
/** |
|
732 |
* @see java.awt.im.InputContext#isCompositionEnabled |
|
733 |
* @exception UnsupportedOperationException when input method is null |
|
734 |
*/ |
|
735 |
public boolean isCompositionEnabled() { |
|
736 |
InputMethod inputMethod = getInputMethod(); |
|
737 |
||
738 |
if (inputMethod == null) { |
|
739 |
throw new UnsupportedOperationException(); |
|
740 |
} |
|
741 |
return inputMethod.isCompositionEnabled(); |
|
742 |
} |
|
743 |
||
744 |
/** |
|
745 |
* @return a string with information about the current input method. |
|
746 |
* @exception UnsupportedOperationException when input method is null |
|
747 |
*/ |
|
748 |
public String getInputMethodInfo() { |
|
749 |
InputMethod inputMethod = getInputMethod(); |
|
750 |
||
751 |
if (inputMethod == null) { |
|
752 |
throw new UnsupportedOperationException("Null input method"); |
|
753 |
} |
|
754 |
||
755 |
String inputMethodInfo = null; |
|
756 |
if (inputMethod instanceof InputMethodAdapter) { |
|
757 |
// returns the information about the host native input method. |
|
758 |
inputMethodInfo = ((InputMethodAdapter)inputMethod). |
|
759 |
getNativeInputMethodInfo(); |
|
760 |
} |
|
761 |
||
762 |
// extracts the information from the InputMethodDescriptor |
|
763 |
// associated with the current java input method. |
|
764 |
if (inputMethodInfo == null && inputMethodLocator != null) { |
|
765 |
inputMethodInfo = inputMethodLocator.getDescriptor(). |
|
766 |
getInputMethodDisplayName(getLocale(), SunToolkit. |
|
767 |
getStartupLocale()); |
|
768 |
} |
|
769 |
||
770 |
if (inputMethodInfo != null && !inputMethodInfo.equals("")) { |
|
771 |
return inputMethodInfo; |
|
772 |
} |
|
773 |
||
774 |
// do our best to return something useful. |
|
775 |
return inputMethod.toString() + "-" + inputMethod.getLocale().toString(); |
|
776 |
} |
|
777 |
||
778 |
/** |
|
779 |
* Turns off the native IM. The native IM is diabled when |
|
780 |
* the deactive method of InputMethod is called. It is |
|
781 |
* delayed until the active method is called on a different |
|
782 |
* peer component. This method is provided to explicitly disable |
|
783 |
* the native IM. |
|
784 |
*/ |
|
785 |
public void disableNativeIM() { |
|
786 |
InputMethod inputMethod = getInputMethod(); |
|
787 |
if (inputMethod != null && inputMethod instanceof InputMethodAdapter) { |
|
788 |
((InputMethodAdapter)inputMethod).disableInputMethod(); |
|
789 |
} |
|
790 |
} |
|
791 |
||
792 |
||
793 |
private synchronized InputMethod getInputMethod() { |
|
794 |
if (inputMethod != null) { |
|
795 |
return inputMethod; |
|
796 |
} |
|
797 |
||
798 |
if (inputMethodCreationFailed) { |
|
799 |
return null; |
|
800 |
} |
|
801 |
||
802 |
inputMethod = getInputMethodInstance(); |
|
803 |
return inputMethod; |
|
804 |
} |
|
805 |
||
806 |
/** |
|
807 |
* Returns an instance of the input method described by |
|
808 |
* the current input method locator. This may be an input |
|
809 |
* method that was previously used and switched out of, |
|
810 |
* or a new instance. The locale, character subsets, and |
|
811 |
* input method context of the input method are set. |
|
812 |
* |
|
813 |
* The inputMethodCreationFailed field is set to true if the |
|
814 |
* instantiation failed. |
|
815 |
* |
|
816 |
* @return an InputMethod instance |
|
817 |
* @see java.awt.im.spi.InputMethod#setInputMethodContext |
|
818 |
* @see java.awt.im.spi.InputMethod#setLocale |
|
819 |
* @see java.awt.im.spi.InputMethod#setCharacterSubsets |
|
820 |
*/ |
|
821 |
private InputMethod getInputMethodInstance() { |
|
822 |
InputMethodLocator locator = inputMethodLocator; |
|
823 |
if (locator == null) { |
|
824 |
inputMethodCreationFailed = true; |
|
825 |
return null; |
|
826 |
} |
|
827 |
||
828 |
Locale locale = locator.getLocale(); |
|
829 |
InputMethod inputMethodInstance = null; |
|
830 |
||
831 |
// see whether we have a previously used input method |
|
832 |
if (usedInputMethods != null) { |
|
833 |
inputMethodInstance = (InputMethod) usedInputMethods.remove(locator.deriveLocator(null)); |
|
834 |
if (inputMethodInstance != null) { |
|
835 |
if (locale != null) { |
|
836 |
inputMethodInstance.setLocale(locale); |
|
837 |
} |
|
838 |
inputMethodInstance.setCharacterSubsets(characterSubsets); |
|
839 |
Boolean state = (Boolean) perInputMethodState.remove(inputMethodInstance); |
|
840 |
if (state != null) { |
|
841 |
enableClientWindowNotification(inputMethodInstance, state.booleanValue()); |
|
842 |
} |
|
843 |
((InputMethodContext) this).setInputMethodSupportsBelowTheSpot( |
|
844 |
(!(inputMethodInstance instanceof InputMethodAdapter)) || |
|
845 |
((InputMethodAdapter) inputMethodInstance).supportsBelowTheSpot()); |
|
846 |
return inputMethodInstance; |
|
847 |
} |
|
848 |
} |
|
849 |
||
850 |
// need to create new instance |
|
851 |
try { |
|
852 |
inputMethodInstance = locator.getDescriptor().createInputMethod(); |
|
853 |
||
854 |
if (locale != null) { |
|
855 |
inputMethodInstance.setLocale(locale); |
|
856 |
} |
|
857 |
inputMethodInstance.setInputMethodContext((InputMethodContext) this); |
|
858 |
inputMethodInstance.setCharacterSubsets(characterSubsets); |
|
859 |
||
860 |
} catch (Exception e) { |
|
861 |
logCreationFailed(e); |
|
862 |
||
863 |
// there are a number of bad things that can happen while creating |
|
864 |
// the input method. In any case, we just continue without an |
|
865 |
// input method. |
|
866 |
inputMethodCreationFailed = true; |
|
867 |
||
868 |
// if the instance has been created, then it means either |
|
869 |
// setLocale() or setInputMethodContext() failed. |
|
870 |
if (inputMethodInstance != null) { |
|
871 |
inputMethodInstance = null; |
|
872 |
} |
|
873 |
} catch (LinkageError e) { |
|
874 |
logCreationFailed(e); |
|
875 |
||
876 |
// same as above |
|
877 |
inputMethodCreationFailed = true; |
|
878 |
} |
|
879 |
((InputMethodContext) this).setInputMethodSupportsBelowTheSpot( |
|
880 |
(!(inputMethodInstance instanceof InputMethodAdapter)) || |
|
881 |
((InputMethodAdapter) inputMethodInstance).supportsBelowTheSpot()); |
|
882 |
return inputMethodInstance; |
|
883 |
} |
|
884 |
||
885 |
private void logCreationFailed(Throwable throwable) { |
|
886 |
String errorTextFormat = Toolkit.getProperty("AWT.InputMethodCreationFailed", |
|
887 |
"Could not create {0}. Reason: {1}"); |
|
888 |
Object[] args = |
|
889 |
{inputMethodLocator.getDescriptor().getInputMethodDisplayName(null, Locale.getDefault()), |
|
890 |
throwable.getLocalizedMessage()}; |
|
891 |
MessageFormat mf = new MessageFormat(errorTextFormat); |
|
3938
ef327bd847c0
6879044: Eliminate the dependency on logging from the AWT/2D/Swing classes
mchung
parents:
1311
diff
changeset
|
892 |
PlatformLogger logger = PlatformLogger.getLogger("sun.awt.im"); |
2 | 893 |
logger.config(mf.format(args)); |
894 |
} |
|
895 |
||
896 |
InputMethodLocator getInputMethodLocator() { |
|
897 |
if (inputMethod != null) { |
|
898 |
return inputMethodLocator.deriveLocator(inputMethod.getLocale()); |
|
899 |
} |
|
900 |
return inputMethodLocator; |
|
901 |
} |
|
902 |
||
903 |
/** |
|
904 |
* @see java.awt.im.InputContext#endComposition |
|
905 |
*/ |
|
906 |
public synchronized void endComposition() { |
|
907 |
if (inputMethod != null) { |
|
908 |
inputMethod.endComposition(); |
|
909 |
} |
|
910 |
} |
|
911 |
||
912 |
/** |
|
913 |
* @see java.awt.im.spi.InputMethodContext#enableClientWindowNotification |
|
914 |
*/ |
|
915 |
synchronized void enableClientWindowNotification(InputMethod requester, |
|
916 |
boolean enable) { |
|
917 |
// in case this request is not from the current input method, |
|
918 |
// store the request and handle it when this requesting input |
|
919 |
// method becomes the current one. |
|
920 |
if (requester != inputMethod) { |
|
921 |
if (perInputMethodState == null) { |
|
922 |
perInputMethodState = new HashMap(5); |
|
923 |
} |
|
438
2ae294e4518c
6613529: Avoid duplicate object creation within JDK packages
dav
parents:
2
diff
changeset
|
924 |
perInputMethodState.put(requester, Boolean.valueOf(enable)); |
2 | 925 |
return; |
926 |
} |
|
927 |
||
928 |
if (clientWindowNotificationEnabled != enable) { |
|
929 |
clientWindowLocation = null; |
|
930 |
clientWindowNotificationEnabled = enable; |
|
931 |
} |
|
932 |
if (clientWindowNotificationEnabled) { |
|
933 |
if (!addedClientWindowListeners()) { |
|
934 |
addClientWindowListeners(); |
|
935 |
} |
|
936 |
if (clientWindowListened != null) { |
|
937 |
clientWindowLocation = null; |
|
938 |
notifyClientWindowChange(clientWindowListened); |
|
939 |
} |
|
940 |
} else { |
|
941 |
if (addedClientWindowListeners()) { |
|
942 |
removeClientWindowListeners(); |
|
943 |
} |
|
944 |
} |
|
945 |
} |
|
946 |
||
947 |
private synchronized void notifyClientWindowChange(Window window) { |
|
948 |
if (inputMethod == null) { |
|
949 |
return; |
|
950 |
} |
|
951 |
||
952 |
// if the window is invisible or iconified, send null to the input method. |
|
953 |
if (!window.isVisible() || |
|
954 |
((window instanceof Frame) && ((Frame)window).getState() == Frame.ICONIFIED)) { |
|
955 |
clientWindowLocation = null; |
|
956 |
inputMethod.notifyClientWindowChange(null); |
|
957 |
return; |
|
958 |
} |
|
959 |
Rectangle location = window.getBounds(); |
|
960 |
if (clientWindowLocation == null || !clientWindowLocation.equals(location)) { |
|
961 |
clientWindowLocation = location; |
|
962 |
inputMethod.notifyClientWindowChange(clientWindowLocation); |
|
963 |
} |
|
964 |
} |
|
965 |
||
966 |
private synchronized void addClientWindowListeners() { |
|
967 |
Component client = getClientComponent(); |
|
968 |
if (client == null) { |
|
969 |
return; |
|
970 |
} |
|
971 |
Window window = getComponentWindow(client); |
|
972 |
if (window == null) { |
|
973 |
return; |
|
974 |
} |
|
975 |
window.addComponentListener(this); |
|
976 |
window.addWindowListener(this); |
|
977 |
clientWindowListened = window; |
|
978 |
} |
|
979 |
||
980 |
private synchronized void removeClientWindowListeners() { |
|
981 |
clientWindowListened.removeComponentListener(this); |
|
982 |
clientWindowListened.removeWindowListener(this); |
|
983 |
clientWindowListened = null; |
|
984 |
} |
|
985 |
||
986 |
/** |
|
987 |
* Returns true if listeners have been set up for client window |
|
988 |
* change notification. |
|
989 |
*/ |
|
990 |
private boolean addedClientWindowListeners() { |
|
991 |
return clientWindowListened != null; |
|
992 |
} |
|
993 |
||
994 |
/* |
|
995 |
* ComponentListener and WindowListener implementation |
|
996 |
*/ |
|
997 |
public void componentResized(ComponentEvent e) { |
|
998 |
notifyClientWindowChange((Window)e.getComponent()); |
|
999 |
} |
|
1000 |
||
1001 |
public void componentMoved(ComponentEvent e) { |
|
1002 |
notifyClientWindowChange((Window)e.getComponent()); |
|
1003 |
} |
|
1004 |
||
1005 |
public void componentShown(ComponentEvent e) { |
|
1006 |
notifyClientWindowChange((Window)e.getComponent()); |
|
1007 |
} |
|
1008 |
||
1009 |
public void componentHidden(ComponentEvent e) { |
|
1010 |
notifyClientWindowChange((Window)e.getComponent()); |
|
1011 |
} |
|
1012 |
||
1013 |
public void windowOpened(WindowEvent e) {} |
|
1014 |
public void windowClosing(WindowEvent e) {} |
|
1015 |
public void windowClosed(WindowEvent e) {} |
|
1016 |
||
1017 |
public void windowIconified(WindowEvent e) { |
|
1018 |
notifyClientWindowChange(e.getWindow()); |
|
1019 |
} |
|
1020 |
||
1021 |
public void windowDeiconified(WindowEvent e) { |
|
1022 |
notifyClientWindowChange(e.getWindow()); |
|
1023 |
} |
|
1024 |
||
1025 |
public void windowActivated(WindowEvent e) {} |
|
1026 |
public void windowDeactivated(WindowEvent e) {} |
|
1027 |
||
1028 |
/** |
|
1029 |
* Initializes the input method selection key definition in preference trees |
|
1030 |
*/ |
|
1031 |
private void initializeInputMethodSelectionKey() { |
|
1032 |
AccessController.doPrivileged(new PrivilegedAction() { |
|
1033 |
public Object run() { |
|
1034 |
// Look in user's tree |
|
1035 |
Preferences root = Preferences.userRoot(); |
|
1036 |
inputMethodSelectionKey = getInputMethodSelectionKeyStroke(root); |
|
1037 |
||
1038 |
if (inputMethodSelectionKey == null) { |
|
1039 |
// Look in system's tree |
|
1040 |
root = Preferences.systemRoot(); |
|
1041 |
inputMethodSelectionKey = getInputMethodSelectionKeyStroke(root); |
|
1042 |
} |
|
1043 |
return null; |
|
1044 |
} |
|
1045 |
}); |
|
1046 |
} |
|
1047 |
||
1048 |
private AWTKeyStroke getInputMethodSelectionKeyStroke(Preferences root) { |
|
1049 |
try { |
|
1050 |
if (root.nodeExists(inputMethodSelectionKeyPath)) { |
|
1051 |
Preferences node = root.node(inputMethodSelectionKeyPath); |
|
1052 |
int keyCode = node.getInt(inputMethodSelectionKeyCodeName, KeyEvent.VK_UNDEFINED); |
|
1053 |
if (keyCode != KeyEvent.VK_UNDEFINED) { |
|
1054 |
int modifiers = node.getInt(inputMethodSelectionKeyModifiersName, 0); |
|
1055 |
return AWTKeyStroke.getAWTKeyStroke(keyCode, modifiers); |
|
1056 |
} |
|
1057 |
} |
|
1058 |
} catch (BackingStoreException bse) { |
|
1059 |
} |
|
1060 |
||
1061 |
return null; |
|
1062 |
} |
|
1063 |
} |