1 /*
2 * Copyright (c) 1997, 2018, 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
48 final class WInputMethod extends InputMethodAdapter
49 {
50 /**
51 * The input method context, which is used to dispatch input method
52 * events to the client component and to request information from
53 * the client component.
54 */
55 private InputMethodContext inputContext;
56
57 private Component awtFocussedComponent;
58 private WComponentPeer awtFocussedComponentPeer = null;
59 private WComponentPeer lastFocussedComponentPeer = null;
60 private boolean isLastFocussedActiveClient = false;
61 private boolean isActive;
62 private int context;
63 private boolean open; //default open status;
64 private int cmode; //default conversion mode;
65 private Locale currentLocale;
66 // indicate whether status window is hidden or not.
67 private boolean statusWindowHidden = false;
68
69 // attribute definition in Win32 (in IMM.H)
70 public static final byte ATTR_INPUT = 0x00;
71 public static final byte ATTR_TARGET_CONVERTED = 0x01;
72 public static final byte ATTR_CONVERTED = 0x02;
73 public static final byte ATTR_TARGET_NOTCONVERTED = 0x03;
74 public static final byte ATTR_INPUT_ERROR = 0x04;
75 // cmode definition in Win32 (in IMM.H)
76 public static final int IME_CMODE_ALPHANUMERIC = 0x0000;
77 public static final int IME_CMODE_NATIVE = 0x0001;
78 public static final int IME_CMODE_KATAKANA = 0x0002;
79 public static final int IME_CMODE_LANGUAGE = 0x0003;
80 public static final int IME_CMODE_FULLSHAPE = 0x0008;
81 public static final int IME_CMODE_HANJACONVERT = 0x0040;
82 public static final int IME_CMODE_ROMAN = 0x0010;
83
84 // flag values for endCompositionNative() behavior
85 private static final boolean COMMIT_INPUT = true;
86 private static final boolean DISCARD_INPUT = false;
87
229 } else {
230 if (subset1 == UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
231 || subset1 == InputSubset.KANJI
232 || subset1 == UnicodeBlock.HIRAGANA)
233 newmode = IME_CMODE_NATIVE | IME_CMODE_FULLSHAPE;
234 else if (subset1 == UnicodeBlock.KATAKANA)
235 newmode = IME_CMODE_NATIVE | IME_CMODE_KATAKANA| IME_CMODE_FULLSHAPE;
236 else if (subset1 == InputSubset.HALFWIDTH_KATAKANA)
237 newmode = IME_CMODE_NATIVE | IME_CMODE_KATAKANA;
238 else if (subset1 == InputSubset.FULLWIDTH_LATIN)
239 newmode = IME_CMODE_FULLSHAPE;
240 else
241 return;
242 setOpenStatus(context, true);
243 newmode |= (getConversionStatus(context)&IME_CMODE_ROMAN); // reserve ROMAN input mode
244 setConversionStatus(context, newmode);
245 }
246 } else if (locale.getLanguage().equals(Locale.KOREAN.getLanguage())) {
247 if (subset1 == UnicodeBlock.BASIC_LATIN || subset1 == InputSubset.LATIN_DIGITS) {
248 setOpenStatus(context, false);
249 } else {
250 if (subset1 == UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
251 || subset1 == InputSubset.HANJA
252 || subset1 == UnicodeBlock.HANGUL_SYLLABLES
253 || subset1 == UnicodeBlock.HANGUL_JAMO
254 || subset1 == UnicodeBlock.HANGUL_COMPATIBILITY_JAMO)
255 newmode = IME_CMODE_NATIVE;
256 else if (subset1 == InputSubset.FULLWIDTH_LATIN)
257 newmode = IME_CMODE_FULLSHAPE;
258 else
259 return;
260 setOpenStatus(context, true);
261 setConversionStatus(context, newmode);
262 }
263 } else if (locale.getLanguage().equals(Locale.CHINESE.getLanguage())) {
264 if (subset1 == UnicodeBlock.BASIC_LATIN || subset1 == InputSubset.LATIN_DIGITS) {
265 setOpenStatus(context, false);
266 } else {
267 if (subset1 == UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
268 || subset1 == InputSubset.TRADITIONAL_HANZI
269 || subset1 == InputSubset.SIMPLIFIED_HANZI)
270 newmode = IME_CMODE_NATIVE;
271 else if (subset1 == InputSubset.FULLWIDTH_LATIN)
272 newmode = IME_CMODE_FULLSHAPE;
273 else
274 return;
275 setOpenStatus(context, true);
276 setConversionStatus(context, newmode);
277 }
278 }
279 }
280
281 @Override
282 public void dispatchEvent(AWTEvent e) {
283 if (e instanceof ComponentEvent) {
284 Component comp = ((ComponentEvent) e).getComponent();
285 if (comp == awtFocussedComponent) {
286 if (awtFocussedComponentPeer == null ||
287 awtFocussedComponentPeer.isDisposed()) {
288 awtFocussedComponentPeer = getNearestNativePeer(comp);
289 }
290 if (awtFocussedComponentPeer != null) {
301 // When the last focussed component peer is different from the
302 // current focussed component or if they are different client
303 // (active or passive), disable native IME for the old focussed
304 // component and enable for the new one.
305 if (lastFocussedComponentPeer != awtFocussedComponentPeer ||
306 isLastFocussedActiveClient != isAc) {
307 if (lastFocussedComponentPeer != null) {
308 disableNativeIME(lastFocussedComponentPeer);
309 }
310 if (awtFocussedComponentPeer != null) {
311 enableNativeIME(awtFocussedComponentPeer, context, !isAc);
312 }
313 lastFocussedComponentPeer = awtFocussedComponentPeer;
314 isLastFocussedActiveClient = isAc;
315 }
316 isActive = true;
317 if (currentLocale != null) {
318 setLocale(currentLocale, true);
319 }
320
321 /* If the status window or Windows language bar is turned off due to
322 native input method was switched to java input method, we
323 have to turn it on otherwise it is gone for good until next time
324 the user turns it on through Windows Control Panel. See details
325 from bug 6252674.
326 */
327 if (statusWindowHidden) {
328 setStatusWindowVisible(awtFocussedComponentPeer, true);
329 statusWindowHidden = false;
330 }
331
332 }
333
334 @Override
335 public void deactivate(boolean isTemporary)
336 {
337 // Sync currentLocale with the Windows keyboard layout which might be changed
338 // by hot key
339 getLocale();
340
341 // Delay calling disableNativeIME until activate is called and the newly
342 // focussed component has a different peer as the last focussed component.
343 if (awtFocussedComponentPeer != null) {
344 lastFocussedComponentPeer = awtFocussedComponentPeer;
345 isLastFocussedActiveClient = haveActiveClient();
346 }
347 isActive = false;
348 }
349
350 /**
351 * Explicitly disable the native IME. Native IME is not disabled when
352 * deactivate is called.
353 */
354 @Override
355 public void disableInputMethod() {
356 if (lastFocussedComponentPeer != null) {
357 disableNativeIME(lastFocussedComponentPeer);
358 lastFocussedComponentPeer = null;
359 isLastFocussedActiveClient = false;
360 }
361 }
362
363 /**
364 * Returns a string with information about the windows input method,
365 * or null.
366 */
367 @Override
632 else
633 return null;
634
635 }
636
637 private native int createNativeContext();
638 private native void destroyNativeContext(int context);
639 private native void enableNativeIME(WComponentPeer peer, int context, boolean useNativeCompWindow);
640 private native void disableNativeIME(WComponentPeer peer);
641 private native void handleNativeIMEEvent(WComponentPeer peer, AWTEvent e);
642 private native void endCompositionNative(int context, boolean flag);
643 private native void setConversionStatus(int context, int cmode);
644 private native int getConversionStatus(int context);
645 private native void setOpenStatus(int context, boolean flag);
646 private native boolean getOpenStatus(int context);
647 private native void setStatusWindowVisible(WComponentPeer peer, boolean visible);
648 private native String getNativeIMMDescription();
649 static native Locale getNativeLocale();
650 static native boolean setNativeLocale(String localeName, boolean onActivate);
651 private native void openCandidateWindow(WComponentPeer peer, int x, int y);
652 }
|
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
48 final class WInputMethod extends InputMethodAdapter
49 {
50 /**
51 * The input method context, which is used to dispatch input method
52 * events to the client component and to request information from
53 * the client component.
54 */
55 private InputMethodContext inputContext;
56
57 private Component awtFocussedComponent;
58 private WComponentPeer awtFocussedComponentPeer = null;
59 private WComponentPeer lastFocussedComponentPeer = null;
60 private boolean isLastFocussedActiveClient = false;
61 private boolean isActive;
62 private int context;
63 private boolean open; //default open status;
64 private int cmode; //default conversion mode;
65 private Locale currentLocale;
66 // indicate whether status window is hidden or not.
67 private boolean statusWindowHidden = false;
68 private boolean hasCompositionString = false;
69
70 // attribute definition in Win32 (in IMM.H)
71 public static final byte ATTR_INPUT = 0x00;
72 public static final byte ATTR_TARGET_CONVERTED = 0x01;
73 public static final byte ATTR_CONVERTED = 0x02;
74 public static final byte ATTR_TARGET_NOTCONVERTED = 0x03;
75 public static final byte ATTR_INPUT_ERROR = 0x04;
76 // cmode definition in Win32 (in IMM.H)
77 public static final int IME_CMODE_ALPHANUMERIC = 0x0000;
78 public static final int IME_CMODE_NATIVE = 0x0001;
79 public static final int IME_CMODE_KATAKANA = 0x0002;
80 public static final int IME_CMODE_LANGUAGE = 0x0003;
81 public static final int IME_CMODE_FULLSHAPE = 0x0008;
82 public static final int IME_CMODE_HANJACONVERT = 0x0040;
83 public static final int IME_CMODE_ROMAN = 0x0010;
84
85 // flag values for endCompositionNative() behavior
86 private static final boolean COMMIT_INPUT = true;
87 private static final boolean DISCARD_INPUT = false;
88
230 } else {
231 if (subset1 == UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
232 || subset1 == InputSubset.KANJI
233 || subset1 == UnicodeBlock.HIRAGANA)
234 newmode = IME_CMODE_NATIVE | IME_CMODE_FULLSHAPE;
235 else if (subset1 == UnicodeBlock.KATAKANA)
236 newmode = IME_CMODE_NATIVE | IME_CMODE_KATAKANA| IME_CMODE_FULLSHAPE;
237 else if (subset1 == InputSubset.HALFWIDTH_KATAKANA)
238 newmode = IME_CMODE_NATIVE | IME_CMODE_KATAKANA;
239 else if (subset1 == InputSubset.FULLWIDTH_LATIN)
240 newmode = IME_CMODE_FULLSHAPE;
241 else
242 return;
243 setOpenStatus(context, true);
244 newmode |= (getConversionStatus(context)&IME_CMODE_ROMAN); // reserve ROMAN input mode
245 setConversionStatus(context, newmode);
246 }
247 } else if (locale.getLanguage().equals(Locale.KOREAN.getLanguage())) {
248 if (subset1 == UnicodeBlock.BASIC_LATIN || subset1 == InputSubset.LATIN_DIGITS) {
249 setOpenStatus(context, false);
250 setConversionStatus(context, IME_CMODE_ALPHANUMERIC);
251 } else {
252 if (subset1 == UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
253 || subset1 == InputSubset.HANJA
254 || subset1 == UnicodeBlock.HANGUL_SYLLABLES
255 || subset1 == UnicodeBlock.HANGUL_JAMO
256 || subset1 == UnicodeBlock.HANGUL_COMPATIBILITY_JAMO)
257 newmode = IME_CMODE_NATIVE;
258 else if (subset1 == InputSubset.FULLWIDTH_LATIN)
259 newmode = IME_CMODE_FULLSHAPE;
260 else
261 return;
262 setOpenStatus(context, true);
263 setConversionStatus(context, newmode);
264 }
265 } else if (locale.getLanguage().equals(Locale.CHINESE.getLanguage())) {
266 if (subset1 == UnicodeBlock.BASIC_LATIN || subset1 == InputSubset.LATIN_DIGITS) {
267 setOpenStatus(context, false);
268 newmode = getConversionStatus(context);
269 newmode &= ~IME_CMODE_FULLSHAPE;
270 setConversionStatus(context, newmode);
271 } else {
272 if (subset1 == UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
273 || subset1 == InputSubset.TRADITIONAL_HANZI
274 || subset1 == InputSubset.SIMPLIFIED_HANZI)
275 newmode = IME_CMODE_NATIVE | IME_CMODE_FULLSHAPE;
276 else if (subset1 == InputSubset.FULLWIDTH_LATIN)
277 newmode = IME_CMODE_FULLSHAPE;
278 else
279 return;
280 setOpenStatus(context, true);
281 setConversionStatus(context, newmode);
282 }
283 }
284 }
285
286 @Override
287 public void dispatchEvent(AWTEvent e) {
288 if (e instanceof ComponentEvent) {
289 Component comp = ((ComponentEvent) e).getComponent();
290 if (comp == awtFocussedComponent) {
291 if (awtFocussedComponentPeer == null ||
292 awtFocussedComponentPeer.isDisposed()) {
293 awtFocussedComponentPeer = getNearestNativePeer(comp);
294 }
295 if (awtFocussedComponentPeer != null) {
306 // When the last focussed component peer is different from the
307 // current focussed component or if they are different client
308 // (active or passive), disable native IME for the old focussed
309 // component and enable for the new one.
310 if (lastFocussedComponentPeer != awtFocussedComponentPeer ||
311 isLastFocussedActiveClient != isAc) {
312 if (lastFocussedComponentPeer != null) {
313 disableNativeIME(lastFocussedComponentPeer);
314 }
315 if (awtFocussedComponentPeer != null) {
316 enableNativeIME(awtFocussedComponentPeer, context, !isAc);
317 }
318 lastFocussedComponentPeer = awtFocussedComponentPeer;
319 isLastFocussedActiveClient = isAc;
320 }
321 isActive = true;
322 if (currentLocale != null) {
323 setLocale(currentLocale, true);
324 }
325
326 // Compare IM's composition string with Java's composition string
327 if (hasCompositionString && !isCompositionStringAvailable(context)) {
328 endCompositionNative(context, DISCARD_INPUT);
329 sendInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
330 EventQueue.getMostRecentEventTime(),
331 null, null, null, null, null, 0, 0, 0);
332 hasCompositionString = false;
333 }
334
335 /* If the status window or Windows language bar is turned off due to
336 native input method was switched to java input method, we
337 have to turn it on otherwise it is gone for good until next time
338 the user turns it on through Windows Control Panel. See details
339 from bug 6252674.
340 */
341 if (statusWindowHidden) {
342 setStatusWindowVisible(awtFocussedComponentPeer, true);
343 statusWindowHidden = false;
344 }
345
346 }
347
348 @Override
349 public void deactivate(boolean isTemporary)
350 {
351 // Sync currentLocale with the Windows keyboard layout which might be changed
352 // by hot key
353 getLocale();
354
355 // Delay calling disableNativeIME until activate is called and the newly
356 // focussed component has a different peer as the last focussed component.
357 if (awtFocussedComponentPeer != null) {
358 lastFocussedComponentPeer = awtFocussedComponentPeer;
359 isLastFocussedActiveClient = haveActiveClient();
360 }
361 isActive = false;
362 hasCompositionString = isCompositionStringAvailable(context);
363 }
364
365 /**
366 * Explicitly disable the native IME. Native IME is not disabled when
367 * deactivate is called.
368 */
369 @Override
370 public void disableInputMethod() {
371 if (lastFocussedComponentPeer != null) {
372 disableNativeIME(lastFocussedComponentPeer);
373 lastFocussedComponentPeer = null;
374 isLastFocussedActiveClient = false;
375 }
376 }
377
378 /**
379 * Returns a string with information about the windows input method,
380 * or null.
381 */
382 @Override
647 else
648 return null;
649
650 }
651
652 private native int createNativeContext();
653 private native void destroyNativeContext(int context);
654 private native void enableNativeIME(WComponentPeer peer, int context, boolean useNativeCompWindow);
655 private native void disableNativeIME(WComponentPeer peer);
656 private native void handleNativeIMEEvent(WComponentPeer peer, AWTEvent e);
657 private native void endCompositionNative(int context, boolean flag);
658 private native void setConversionStatus(int context, int cmode);
659 private native int getConversionStatus(int context);
660 private native void setOpenStatus(int context, boolean flag);
661 private native boolean getOpenStatus(int context);
662 private native void setStatusWindowVisible(WComponentPeer peer, boolean visible);
663 private native String getNativeIMMDescription();
664 static native Locale getNativeLocale();
665 static native boolean setNativeLocale(String localeName, boolean onActivate);
666 private native void openCandidateWindow(WComponentPeer peer, int x, int y);
667 private native boolean isCompositionStringAvailable(int context);
668 }
|