1 /* 2 * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27 package sun.awt.windows; 28 29 import java.awt.*; 30 import java.awt.peer.*; 31 import java.awt.event.*; 32 import java.awt.im.*; 33 import java.awt.im.spi.InputMethodContext; 34 import java.awt.font.*; 35 import java.text.*; 36 import java.text.AttributedCharacterIterator.Attribute; 37 import java.lang.Character.Subset; 38 import java.lang.Character.UnicodeBlock; 39 import java.util.Collections; 40 import java.util.HashMap; 41 import java.util.Locale; 42 import java.util.Map; 43 44 import sun.awt.AWTAccessor; 45 import sun.awt.AWTAccessor.ComponentAccessor; 46 import sun.awt.im.InputMethodAdapter; 47 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 89 private static Map<TextAttribute,Object> [] highlightStyles; 90 91 // Initialize highlight mapping table 92 static { 93 @SuppressWarnings({"rawtypes", "unchecked"}) 94 Map<TextAttribute,Object> styles[] = new Map[4]; 95 HashMap<TextAttribute,Object> map; 96 97 // UNSELECTED_RAW_TEXT_HIGHLIGHT 98 map = new HashMap<>(1); map.put(TextAttribute.INPUT_METHOD_UNDERLINE, TextAttribute.UNDERLINE_LOW_DOTTED)99 map.put(TextAttribute.INPUT_METHOD_UNDERLINE, TextAttribute.UNDERLINE_LOW_DOTTED); 100 styles[0] = Collections.unmodifiableMap(map); 101 102 // SELECTED_RAW_TEXT_HIGHLIGHT 103 map = new HashMap<>(1); map.put(TextAttribute.INPUT_METHOD_UNDERLINE, TextAttribute.UNDERLINE_LOW_GRAY)104 map.put(TextAttribute.INPUT_METHOD_UNDERLINE, TextAttribute.UNDERLINE_LOW_GRAY); 105 styles[1] = Collections.unmodifiableMap(map); 106 107 // UNSELECTED_CONVERTED_TEXT_HIGHLIGHT 108 map = new HashMap<>(1); map.put(TextAttribute.INPUT_METHOD_UNDERLINE, TextAttribute.UNDERLINE_LOW_DOTTED)109 map.put(TextAttribute.INPUT_METHOD_UNDERLINE, TextAttribute.UNDERLINE_LOW_DOTTED); 110 styles[2] = Collections.unmodifiableMap(map); 111 112 // SELECTED_CONVERTED_TEXT_HIGHLIGHT 113 map = new HashMap<>(4); 114 Color navyBlue = new Color(0, 0, 128); map.put(TextAttribute.FOREGROUND, navyBlue)115 map.put(TextAttribute.FOREGROUND, navyBlue); map.put(TextAttribute.BACKGROUND, Color.white)116 map.put(TextAttribute.BACKGROUND, Color.white); map.put(TextAttribute.SWAP_COLORS, TextAttribute.SWAP_COLORS_ON)117 map.put(TextAttribute.SWAP_COLORS, TextAttribute.SWAP_COLORS_ON); map.put(TextAttribute.INPUT_METHOD_UNDERLINE, TextAttribute.UNDERLINE_LOW_ONE_PIXEL)118 map.put(TextAttribute.INPUT_METHOD_UNDERLINE, TextAttribute.UNDERLINE_LOW_ONE_PIXEL); 119 styles[3] = Collections.unmodifiableMap(map); 120 121 highlightStyles = styles; 122 } 123 WInputMethod()124 public WInputMethod() 125 { 126 context = createNativeContext(); 127 cmode = getConversionStatus(context); 128 open = getOpenStatus(context); 129 currentLocale = getNativeLocale(); 130 if (currentLocale == null) { 131 currentLocale = Locale.getDefault(); 132 } 133 } 134 135 @Override 136 @SuppressWarnings("deprecation") finalize()137 protected void finalize() throws Throwable 138 { 139 // Release the resources used by the native input context. 140 if (context!=0) { 141 destroyNativeContext(context); 142 context=0; 143 } 144 super.finalize(); 145 } 146 147 @Override setInputMethodContext(InputMethodContext context)148 public synchronized void setInputMethodContext(InputMethodContext context) { 149 inputContext = context; 150 } 151 152 @Override dispose()153 public void dispose() { 154 // Due to a memory management problem in Windows 98, we should retain 155 // the native input context until this object is finalized. So do 156 // nothing here. 157 } 158 159 /** 160 * Returns null. 161 * 162 * @see java.awt.im.spi.InputMethod#getControlObject 163 */ 164 @Override getControlObject()165 public Object getControlObject() { 166 return null; 167 } 168 169 @Override setLocale(Locale lang)170 public boolean setLocale(Locale lang) { 171 return setLocale(lang, false); 172 } 173 setLocale(Locale lang, boolean onActivate)174 private boolean setLocale(Locale lang, boolean onActivate) { 175 Locale[] available = WInputMethodDescriptor.getAvailableLocalesInternal(); 176 for (int i = 0; i < available.length; i++) { 177 Locale locale = available[i]; 178 if (lang.equals(locale) || 179 // special compatibility rule for Japanese and Korean 180 locale.equals(Locale.JAPAN) && lang.equals(Locale.JAPANESE) || 181 locale.equals(Locale.KOREA) && lang.equals(Locale.KOREAN)) { 182 if (isActive) { 183 setNativeLocale(locale.toLanguageTag(), onActivate); 184 } 185 currentLocale = locale; 186 return true; 187 } 188 } 189 return false; 190 } 191 192 @Override getLocale()193 public Locale getLocale() { 194 if (isActive) { 195 currentLocale = getNativeLocale(); 196 if (currentLocale == null) { 197 currentLocale = Locale.getDefault(); 198 } 199 } 200 return currentLocale; 201 } 202 203 /** 204 * Implements InputMethod.setCharacterSubsets for Windows. 205 * 206 * @see java.awt.im.spi.InputMethod#setCharacterSubsets 207 */ 208 @Override setCharacterSubsets(Subset[] subsets)209 public void setCharacterSubsets(Subset[] subsets) { 210 if (subsets == null){ 211 setConversionStatus(context, cmode); 212 setOpenStatus(context, open); 213 return; 214 } 215 216 // Use first subset only. Other subsets in array is ignored. 217 // This is restriction of Win32 implementation. 218 Subset subset1 = subsets[0]; 219 220 Locale locale = getNativeLocale(); 221 int newmode; 222 223 if (locale == null) { 224 return; 225 } 226 227 if (locale.getLanguage().equals(Locale.JAPANESE.getLanguage())) { 228 if (subset1 == UnicodeBlock.BASIC_LATIN || subset1 == InputSubset.LATIN_DIGITS) { 229 setOpenStatus(context, false); 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 dispatchEvent(AWTEvent e)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) { 296 handleNativeIMEEvent(awtFocussedComponentPeer, e); 297 } 298 } 299 } 300 } 301 302 @Override activate()303 public void activate() { 304 boolean isAc = haveActiveClient(); 305 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 deactivate(boolean isTemporary)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 // IME is going to be disabled commit the composition string 365 if (hasCompositionString) { 366 endComposition(); 367 } 368 } 369 370 /** 371 * Explicitly disable the native IME. Native IME is not disabled when 372 * deactivate is called. 373 */ 374 @Override disableInputMethod()375 public void disableInputMethod() { 376 if (lastFocussedComponentPeer != null) { 377 disableNativeIME(lastFocussedComponentPeer); 378 lastFocussedComponentPeer = null; 379 isLastFocussedActiveClient = false; 380 } 381 } 382 383 /** 384 * Returns a string with information about the windows input method, 385 * or null. 386 */ 387 @Override getNativeInputMethodInfo()388 public String getNativeInputMethodInfo() { 389 return getNativeIMMDescription(); 390 } 391 392 /** 393 * @see sun.awt.im.InputMethodAdapter#stopListening 394 * This method is called when the input method is swapped out. 395 * Calling stopListening to give other input method the keybaord input 396 * focus. 397 */ 398 @Override stopListening()399 protected void stopListening() { 400 // Since the native input method is not disabled when deactivate is 401 // called, we need to call disableInputMethod to explicitly turn off the 402 // native IME. 403 disableInputMethod(); 404 } 405 406 // implements sun.awt.im.InputMethodAdapter.setAWTFocussedComponent 407 @Override setAWTFocussedComponent(Component component)408 protected void setAWTFocussedComponent(Component component) { 409 if (component == null) { 410 return; 411 } 412 WComponentPeer peer = getNearestNativePeer(component); 413 if (isActive) { 414 // deactivate/activate are being suppressed during a focus change - 415 // this may happen when an input method window is made visible 416 if (awtFocussedComponentPeer != null) { 417 disableNativeIME(awtFocussedComponentPeer); 418 } 419 if (peer != null) { 420 enableNativeIME(peer, context, !haveActiveClient()); 421 } 422 } 423 awtFocussedComponent = component; 424 awtFocussedComponentPeer = peer; 425 } 426 427 // implements java.awt.im.spi.InputMethod.hideWindows 428 @Override hideWindows()429 public void hideWindows() { 430 if (awtFocussedComponentPeer != null) { 431 /* Hide the native status window including the Windows language 432 bar if it is on. One typical senario this method 433 gets called is when the native input method is 434 switched to java input method, for example. 435 */ 436 setStatusWindowVisible(awtFocussedComponentPeer, false); 437 statusWindowHidden = true; 438 } 439 } 440 441 /** 442 * @see java.awt.im.spi.InputMethod#removeNotify 443 */ 444 @Override removeNotify()445 public void removeNotify() { 446 endCompositionNative(context, DISCARD_INPUT); 447 awtFocussedComponent = null; 448 awtFocussedComponentPeer = null; 449 } 450 451 /** 452 * @see java.awt.Toolkit#mapInputMethodHighlight 453 */ mapInputMethodHighlight(InputMethodHighlight highlight)454 static Map<TextAttribute,?> mapInputMethodHighlight(InputMethodHighlight highlight) { 455 int index; 456 int state = highlight.getState(); 457 if (state == InputMethodHighlight.RAW_TEXT) { 458 index = 0; 459 } else if (state == InputMethodHighlight.CONVERTED_TEXT) { 460 index = 2; 461 } else { 462 return null; 463 } 464 if (highlight.isSelected()) { 465 index += 1; 466 } 467 return highlightStyles[index]; 468 } 469 470 // see sun.awt.im.InputMethodAdapter.supportsBelowTheSpot 471 @Override supportsBelowTheSpot()472 protected boolean supportsBelowTheSpot() { 473 return true; 474 } 475 476 @Override endComposition()477 public void endComposition() 478 { 479 //right now the native endCompositionNative() just cancel 480 //the composition string, maybe a commtting is desired 481 endCompositionNative(context, 482 (haveActiveClient() ? COMMIT_INPUT : DISCARD_INPUT)); 483 } 484 485 /** 486 * @see java.awt.im.spi.InputMethod#setCompositionEnabled(boolean) 487 */ 488 @Override setCompositionEnabled(boolean enable)489 public void setCompositionEnabled(boolean enable) { 490 setOpenStatus(context, enable); 491 } 492 493 /** 494 * @see java.awt.im.spi.InputMethod#isCompositionEnabled 495 */ 496 @Override isCompositionEnabled()497 public boolean isCompositionEnabled() { 498 return getOpenStatus(context); 499 } 500 sendInputMethodEvent(int id, long when, String text, int[] clauseBoundary, String[] clauseReading, int[] attributeBoundary, byte[] attributeValue, int commitedTextLength, int caretPos, int visiblePos)501 public void sendInputMethodEvent(int id, long when, String text, 502 int[] clauseBoundary, String[] clauseReading, 503 int[] attributeBoundary, byte[] attributeValue, 504 int commitedTextLength, int caretPos, int visiblePos) 505 { 506 507 AttributedCharacterIterator iterator = null; 508 509 if (text!=null) { 510 511 // construct AttributedString 512 AttributedString attrStr = new AttributedString(text); 513 514 // set Language Information 515 attrStr.addAttribute(Attribute.LANGUAGE, 516 Locale.getDefault(), 0, text.length()); 517 518 // set Clause and Reading Information 519 if (clauseBoundary!=null && clauseReading!=null && 520 clauseReading.length!=0 && clauseBoundary.length==clauseReading.length+1 && 521 clauseBoundary[0]==0 && clauseBoundary[clauseReading.length]<=text.length() ) 522 { 523 for (int i=0; i<clauseBoundary.length-1; i++) { 524 attrStr.addAttribute(Attribute.INPUT_METHOD_SEGMENT, 525 new Annotation(null), clauseBoundary[i], clauseBoundary[i+1]); 526 attrStr.addAttribute(Attribute.READING, 527 new Annotation(clauseReading[i]), clauseBoundary[i], clauseBoundary[i+1]); 528 } 529 } else { 530 // if (clauseBoundary != null) 531 // System.out.println("Invalid clause information!"); 532 533 attrStr.addAttribute(Attribute.INPUT_METHOD_SEGMENT, 534 new Annotation(null), 0, text.length()); 535 attrStr.addAttribute(Attribute.READING, 536 new Annotation(""), 0, text.length()); 537 } 538 539 // set Hilight Information 540 if (attributeBoundary!=null && attributeValue!=null && 541 attributeValue.length!=0 && attributeBoundary.length==attributeValue.length+1 && 542 attributeBoundary[0]==0 && attributeBoundary[attributeValue.length]==text.length() ) 543 { 544 for (int i=0; i<attributeBoundary.length-1; i++) { 545 InputMethodHighlight highlight; 546 switch (attributeValue[i]) { 547 case ATTR_TARGET_CONVERTED: 548 highlight = InputMethodHighlight.SELECTED_CONVERTED_TEXT_HIGHLIGHT; 549 break; 550 case ATTR_CONVERTED: 551 highlight = InputMethodHighlight.UNSELECTED_CONVERTED_TEXT_HIGHLIGHT; 552 break; 553 case ATTR_TARGET_NOTCONVERTED: 554 highlight = InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT; 555 break; 556 case ATTR_INPUT: 557 case ATTR_INPUT_ERROR: 558 default: 559 highlight = InputMethodHighlight.UNSELECTED_RAW_TEXT_HIGHLIGHT; 560 break; 561 } 562 attrStr.addAttribute(TextAttribute.INPUT_METHOD_HIGHLIGHT, 563 highlight, 564 attributeBoundary[i], attributeBoundary[i+1]); 565 } 566 } else { 567 // if (attributeBoundary != null) 568 // System.out.println("Invalid attribute information!"); 569 570 attrStr.addAttribute(TextAttribute.INPUT_METHOD_HIGHLIGHT, 571 InputMethodHighlight.UNSELECTED_CONVERTED_TEXT_HIGHLIGHT, 572 0, text.length()); 573 } 574 575 // get iterator 576 iterator = attrStr.getIterator(); 577 578 } 579 580 Component source = getClientComponent(); 581 if (source == null) 582 return; 583 584 InputMethodEvent event = new InputMethodEvent(source, 585 id, 586 when, 587 iterator, 588 commitedTextLength, 589 TextHitInfo.leading(caretPos), 590 TextHitInfo.leading(visiblePos)); 591 WToolkit.postEvent(WToolkit.targetToAppContext(source), event); 592 } 593 inquireCandidatePosition()594 public void inquireCandidatePosition() 595 { 596 Component source = getClientComponent(); 597 if (source == null) { 598 return; 599 } 600 // This call should return immediately just to cause 601 // InputMethodRequests.getTextLocation be called within 602 // AWT Event thread. Otherwise, a potential deadlock 603 // could happen. 604 Runnable r = new Runnable() { 605 @Override 606 public void run() { 607 int x = 0; 608 int y = 0; 609 Component client = getClientComponent(); 610 611 if (client != null) { 612 if (!client.isShowing()) { 613 return; 614 } 615 if (haveActiveClient()) { 616 Rectangle rc = inputContext.getTextLocation(TextHitInfo.leading(0)); 617 x = rc.x; 618 y = rc.y + rc.height; 619 } else { 620 Point pt = client.getLocationOnScreen(); 621 Dimension size = client.getSize(); 622 x = pt.x; 623 y = pt.y + size.height; 624 } 625 } 626 627 openCandidateWindow(awtFocussedComponentPeer, x, y); 628 } 629 }; 630 WToolkit.postEvent(WToolkit.targetToAppContext(source), 631 new InvocationEvent(source, r)); 632 } 633 634 // java.awt.Toolkit#getNativeContainer() is not available 635 // from this package getNearestNativePeer(Component comp)636 private WComponentPeer getNearestNativePeer(Component comp) 637 { 638 if (comp==null) return null; 639 final ComponentAccessor acc = AWTAccessor.getComponentAccessor(); 640 ComponentPeer peer = acc.getPeer(comp); 641 if (peer==null) return null; 642 643 while (peer instanceof java.awt.peer.LightweightPeer) { 644 comp = comp.getParent(); 645 if (comp==null) return null; 646 peer = acc.getPeer(comp); 647 if (peer==null) return null; 648 } 649 650 if (peer instanceof WComponentPeer) 651 return (WComponentPeer)peer; 652 else 653 return null; 654 655 } 656 createNativeContext()657 private native int createNativeContext(); destroyNativeContext(int context)658 private native void destroyNativeContext(int context); enableNativeIME(WComponentPeer peer, int context, boolean useNativeCompWindow)659 private native void enableNativeIME(WComponentPeer peer, int context, boolean useNativeCompWindow); disableNativeIME(WComponentPeer peer)660 private native void disableNativeIME(WComponentPeer peer); handleNativeIMEEvent(WComponentPeer peer, AWTEvent e)661 private native void handleNativeIMEEvent(WComponentPeer peer, AWTEvent e); endCompositionNative(int context, boolean flag)662 private native void endCompositionNative(int context, boolean flag); setConversionStatus(int context, int cmode)663 private native void setConversionStatus(int context, int cmode); getConversionStatus(int context)664 private native int getConversionStatus(int context); setOpenStatus(int context, boolean flag)665 private native void setOpenStatus(int context, boolean flag); getOpenStatus(int context)666 private native boolean getOpenStatus(int context); setStatusWindowVisible(WComponentPeer peer, boolean visible)667 private native void setStatusWindowVisible(WComponentPeer peer, boolean visible); getNativeIMMDescription()668 private native String getNativeIMMDescription(); getNativeLocale()669 static native Locale getNativeLocale(); setNativeLocale(String localeName, boolean onActivate)670 static native boolean setNativeLocale(String localeName, boolean onActivate); openCandidateWindow(WComponentPeer peer, int x, int y)671 private native void openCandidateWindow(WComponentPeer peer, int x, int y); isCompositionStringAvailable(int context)672 private native boolean isCompositionStringAvailable(int context); 673 } 674