1 /*
   2  * Copyright (c) 1997, 2008, 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 import sun.awt.im.InputMethodAdapter;
  44 
  45 public class WInputMethod extends InputMethodAdapter
  46 {
  47     /**
  48      * The input method context, which is used to dispatch input method
  49      * events to the client component and to request information from
  50      * the client component.
  51      */
  52     private InputMethodContext inputContext;
  53 
  54     private Component awtFocussedComponent;
  55     private WComponentPeer awtFocussedComponentPeer = null;
  56     private WComponentPeer lastFocussedComponentPeer = null;
  57     private boolean isLastFocussedActiveClient = false;
  58     private boolean isActive;
  59     private int context;
  60     private boolean open; //default open status;
  61     private int cmode;    //default conversion mode;
  62     private Locale currentLocale;
  63     // indicate whether status window is hidden or not.
  64     private boolean statusWindowHidden = false;
  65 
  66     // attribute definition in Win32 (in IMM.H)
  67     public final static byte ATTR_INPUT                 = 0x00;
  68     public final static byte ATTR_TARGET_CONVERTED      = 0x01;
  69     public final static byte ATTR_CONVERTED             = 0x02;
  70     public final static byte ATTR_TARGET_NOTCONVERTED   = 0x03;
  71     public final static byte ATTR_INPUT_ERROR           = 0x04;
  72     // cmode definition in Win32 (in IMM.H)
  73     public final static int  IME_CMODE_ALPHANUMERIC     = 0x0000;
  74     public final static int  IME_CMODE_NATIVE           = 0x0001;
  75     public final static int  IME_CMODE_KATAKANA         = 0x0002;
  76     public final static int  IME_CMODE_LANGUAGE         = 0x0003;
  77     public final static int  IME_CMODE_FULLSHAPE        = 0x0008;
  78     public final static int  IME_CMODE_HANJACONVERT     = 0x0040;
  79     public final static int  IME_CMODE_ROMAN            = 0x0010;
  80 
  81     // flag values for endCompositionNative() behavior
  82     private final static boolean COMMIT_INPUT           = true;
  83     private final static boolean DISCARD_INPUT          = false;
  84 
  85     private static Map[] highlightStyles;
  86 
  87     // Initialize highlight mapping table
  88     static {
  89         Map styles[] = new Map[4];
  90         HashMap map;
  91 
  92         // UNSELECTED_RAW_TEXT_HIGHLIGHT
  93         map = new HashMap(1);
  94         map.put(TextAttribute.INPUT_METHOD_UNDERLINE, TextAttribute.UNDERLINE_LOW_DOTTED);
  95         styles[0] = Collections.unmodifiableMap(map);
  96 
  97         // SELECTED_RAW_TEXT_HIGHLIGHT
  98         map = new HashMap(1);
  99         map.put(TextAttribute.INPUT_METHOD_UNDERLINE, TextAttribute.UNDERLINE_LOW_GRAY);
 100         styles[1] = Collections.unmodifiableMap(map);
 101 
 102         // UNSELECTED_CONVERTED_TEXT_HIGHLIGHT
 103         map = new HashMap(1);
 104         map.put(TextAttribute.INPUT_METHOD_UNDERLINE, TextAttribute.UNDERLINE_LOW_DOTTED);
 105         styles[2] = Collections.unmodifiableMap(map);
 106 
 107         // SELECTED_CONVERTED_TEXT_HIGHLIGHT
 108         map = new HashMap(4);
 109         Color navyBlue = new Color(0, 0, 128);
 110         map.put(TextAttribute.FOREGROUND, navyBlue);
 111         map.put(TextAttribute.BACKGROUND, Color.white);
 112         map.put(TextAttribute.SWAP_COLORS, TextAttribute.SWAP_COLORS_ON);
 113         map.put(TextAttribute.INPUT_METHOD_UNDERLINE, TextAttribute.UNDERLINE_LOW_ONE_PIXEL);
 114         styles[3] = Collections.unmodifiableMap(map);
 115 
 116         highlightStyles = styles;
 117     }
 118 
 119     public WInputMethod()
 120     {
 121         context = createNativeContext();
 122         cmode = getConversionStatus(context);
 123         open = getOpenStatus(context);
 124         currentLocale = getNativeLocale();
 125         if (currentLocale == null) {
 126             currentLocale = Locale.getDefault();
 127         }
 128     }
 129 
 130     protected void finalize() throws Throwable
 131     {
 132         // Release the resources used by the native input context.
 133         if (context!=0) {
 134             destroyNativeContext(context);
 135             context=0;
 136         }
 137         super.finalize();
 138     }
 139 
 140     public synchronized void setInputMethodContext(InputMethodContext context) {
 141         inputContext = context;
 142     }
 143 
 144     public final void dispose() {
 145         // Due to a memory management problem in Windows 98, we should retain
 146         // the native input context until this object is finalized. So do
 147         // nothing here.
 148     }
 149 
 150     /**
 151      * Returns null.
 152      *
 153      * @see java.awt.im.spi.InputMethod#getControlObject
 154      */
 155     public Object getControlObject() {
 156         return null;
 157     }
 158 
 159     public boolean setLocale(Locale lang) {
 160         return setLocale(lang, false);
 161     }
 162 
 163     private boolean setLocale(Locale lang, boolean onActivate) {
 164         Locale[] available = WInputMethodDescriptor.getAvailableLocalesInternal();
 165         for (int i = 0; i < available.length; i++) {
 166             Locale locale = available[i];
 167             if (lang.equals(locale) ||
 168                     // special compatibility rule for Japanese and Korean
 169                     locale.equals(Locale.JAPAN) && lang.equals(Locale.JAPANESE) ||
 170                     locale.equals(Locale.KOREA) && lang.equals(Locale.KOREAN)) {
 171                 if (isActive) {
 172                     setNativeLocale(locale.toLanguageTag(), onActivate);
 173                 }
 174                 currentLocale = locale;
 175                 return true;
 176             }
 177         }
 178         return false;
 179     }
 180 
 181     public Locale getLocale() {
 182         if (isActive) {
 183             currentLocale = getNativeLocale();
 184             if (currentLocale == null) {
 185                 currentLocale = Locale.getDefault();
 186             }
 187         }
 188         return currentLocale;
 189     }
 190 
 191     /**
 192      * Implements InputMethod.setCharacterSubsets for Windows.
 193      *
 194      * @see java.awt.im.spi.InputMethod#setCharacterSubsets
 195      */
 196     public void setCharacterSubsets(Subset[] subsets) {
 197         if (subsets == null){
 198             setConversionStatus(context, cmode);
 199             setOpenStatus(context, open);
 200             return;
 201         }
 202 
 203         // Use first subset only. Other subsets in array is ignored.
 204         // This is restriction of Win32 implementation.
 205         Subset subset1 = subsets[0];
 206 
 207         Locale locale = getNativeLocale();
 208         int newmode;
 209 
 210         if (locale == null) {
 211             return;
 212         }
 213 
 214         if (locale.getLanguage().equals(Locale.JAPANESE.getLanguage())) {
 215             if (subset1 == UnicodeBlock.BASIC_LATIN || subset1 == InputSubset.LATIN_DIGITS) {
 216                 setOpenStatus(context, false);
 217             } else {
 218                 if (subset1 == UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
 219                     || subset1 == InputSubset.KANJI
 220                     || subset1 == UnicodeBlock.HIRAGANA)
 221                     newmode = IME_CMODE_NATIVE | IME_CMODE_FULLSHAPE;
 222                 else if (subset1 == UnicodeBlock.KATAKANA)
 223                     newmode = IME_CMODE_NATIVE | IME_CMODE_KATAKANA| IME_CMODE_FULLSHAPE;
 224                 else if (subset1 == InputSubset.HALFWIDTH_KATAKANA)
 225                     newmode = IME_CMODE_NATIVE | IME_CMODE_KATAKANA;
 226                 else if (subset1 == InputSubset.FULLWIDTH_LATIN)
 227                     newmode = IME_CMODE_FULLSHAPE;
 228                 else
 229                     return;
 230                 setOpenStatus(context, true);
 231                 newmode |= (getConversionStatus(context)&IME_CMODE_ROMAN);   // reserve ROMAN input mode
 232                 setConversionStatus(context, newmode);
 233             }
 234         } else if (locale.getLanguage().equals(Locale.KOREAN.getLanguage())) {
 235             if (subset1 == UnicodeBlock.BASIC_LATIN || subset1 == InputSubset.LATIN_DIGITS) {
 236                 setOpenStatus(context, false);
 237             } else {
 238                 if (subset1 == UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
 239                     || subset1 == InputSubset.HANJA
 240                     || subset1 == UnicodeBlock.HANGUL_SYLLABLES
 241                     || subset1 == UnicodeBlock.HANGUL_JAMO
 242                     || subset1 == UnicodeBlock.HANGUL_COMPATIBILITY_JAMO)
 243                     newmode = IME_CMODE_NATIVE;
 244                 else if (subset1 == InputSubset.FULLWIDTH_LATIN)
 245                     newmode = IME_CMODE_FULLSHAPE;
 246                 else
 247                     return;
 248                 setOpenStatus(context, true);
 249                 setConversionStatus(context, newmode);
 250             }
 251         } else if (locale.getLanguage().equals(Locale.CHINESE.getLanguage())) {
 252             if (subset1 == UnicodeBlock.BASIC_LATIN || subset1 == InputSubset.LATIN_DIGITS) {
 253                 setOpenStatus(context, false);
 254             } else {
 255                 if (subset1 == UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
 256                     || subset1 == InputSubset.TRADITIONAL_HANZI
 257                     || subset1 == InputSubset.SIMPLIFIED_HANZI)
 258                     newmode = IME_CMODE_NATIVE;
 259                 else if (subset1 == InputSubset.FULLWIDTH_LATIN)
 260                     newmode = IME_CMODE_FULLSHAPE;
 261                 else
 262                     return;
 263                 setOpenStatus(context, true);
 264                 setConversionStatus(context, newmode);
 265             }
 266         }
 267     }
 268 
 269     public void dispatchEvent(AWTEvent e) {
 270         if (e instanceof ComponentEvent) {
 271             Component comp = ((ComponentEvent) e).getComponent();
 272             if (comp == awtFocussedComponent) {
 273                 if (awtFocussedComponentPeer == null ||
 274                     awtFocussedComponentPeer.isDisposed()) {
 275                     awtFocussedComponentPeer = getNearestNativePeer(comp);
 276                 }
 277                 if (awtFocussedComponentPeer != null) {
 278                     handleNativeIMEEvent(awtFocussedComponentPeer, e);
 279                 }
 280             }
 281         }
 282     }
 283 
 284     public void activate() {
 285         boolean isAc = haveActiveClient();
 286 
 287         // When the last focussed component peer is different from the
 288         // current focussed component or if they are different client
 289         // (active or passive), disable native IME for the old focussed
 290         // component and enable for the new one.
 291         if (lastFocussedComponentPeer != awtFocussedComponentPeer ||
 292             isLastFocussedActiveClient != isAc) {
 293             if (lastFocussedComponentPeer != null) {
 294                 disableNativeIME(lastFocussedComponentPeer);
 295             }
 296             if (awtFocussedComponentPeer != null) {
 297                 enableNativeIME(awtFocussedComponentPeer, context, !isAc);
 298             }
 299             lastFocussedComponentPeer = awtFocussedComponentPeer;
 300             isLastFocussedActiveClient = isAc;
 301         }
 302         isActive = true;
 303         if (currentLocale != null) {
 304             setLocale(currentLocale, true);
 305         }
 306 
 307         /* If the status window or Windows language bar is turned off due to
 308            native input method was switched to java input method, we
 309            have to turn it on otherwise it is gone for good until next time
 310            the user turns it on through Windows Control Panel. See details
 311            from bug 6252674.
 312         */
 313         if (statusWindowHidden) {
 314             setStatusWindowVisible(awtFocussedComponentPeer, true);
 315             statusWindowHidden = false;
 316         }
 317 
 318     }
 319 
 320     public void deactivate(boolean isTemporary)
 321     {
 322         // Sync currentLocale with the Windows keyboard layout which might be changed
 323         // by hot key
 324         getLocale();
 325 
 326         // Delay calling disableNativeIME until activate is called and the newly
 327         // focussed component has a different peer as the last focussed component.
 328         if (awtFocussedComponentPeer != null) {
 329             lastFocussedComponentPeer = awtFocussedComponentPeer;
 330             isLastFocussedActiveClient = haveActiveClient();
 331         }
 332         isActive = false;
 333     }
 334 
 335     /**
 336      * Explicitly disable the native IME. Native IME is not disabled when
 337      * deactivate is called.
 338      */
 339     public void disableInputMethod() {
 340         if (lastFocussedComponentPeer != null) {
 341             disableNativeIME(lastFocussedComponentPeer);
 342             lastFocussedComponentPeer = null;
 343             isLastFocussedActiveClient = false;
 344         }
 345     }
 346 
 347     /**
 348      * Returns a string with information about the windows input method,
 349      * or null.
 350      */
 351     public String getNativeInputMethodInfo() {
 352         return getNativeIMMDescription();
 353     }
 354 
 355      /**
 356      * @see sun.awt.im.InputMethodAdapter#stopListening
 357      * This method is called when the input method is swapped out.
 358      * Calling stopListening to give other input method the keybaord input
 359      * focus.
 360      */
 361     protected void stopListening() {
 362         // Since the native input method is not disabled when deactivate is
 363         // called, we need to call disableInputMethod to explicitly turn off the
 364         // native IME.
 365         disableInputMethod();
 366     }
 367 
 368     // implements sun.awt.im.InputMethodAdapter.setAWTFocussedComponent
 369     protected void setAWTFocussedComponent(Component component) {
 370         if (component == null) {
 371             return;
 372         }
 373         WComponentPeer peer = getNearestNativePeer(component);
 374         if (isActive) {
 375             // deactivate/activate are being suppressed during a focus change -
 376             // this may happen when an input method window is made visible
 377             if (awtFocussedComponentPeer != null) {
 378                 disableNativeIME(awtFocussedComponentPeer);
 379             }
 380             if (peer != null) {
 381                 enableNativeIME(peer, context, !haveActiveClient());
 382             }
 383         }
 384         awtFocussedComponent = component;
 385         awtFocussedComponentPeer = peer;
 386     }
 387 
 388     // implements java.awt.im.spi.InputMethod.hideWindows
 389     public void hideWindows() {
 390         if (awtFocussedComponentPeer != null) {
 391             /* Hide the native status window including the Windows language
 392                bar if it is on. One typical senario this method
 393                gets called is when the native input method is
 394                switched to java input method, for example.
 395             */
 396             setStatusWindowVisible(awtFocussedComponentPeer, false);
 397             statusWindowHidden = true;
 398         }
 399     }
 400 
 401     /**
 402      * @see java.awt.im.spi.InputMethod#removeNotify
 403      */
 404     public void removeNotify() {
 405         endCompositionNative(context, DISCARD_INPUT);
 406         awtFocussedComponent = null;
 407         awtFocussedComponentPeer = null;
 408     }
 409 
 410     /**
 411      * @see java.awt.Toolkit#mapInputMethodHighlight
 412      */
 413     static Map mapInputMethodHighlight(InputMethodHighlight highlight) {
 414         int index;
 415         int state = highlight.getState();
 416         if (state == InputMethodHighlight.RAW_TEXT) {
 417             index = 0;
 418         } else if (state == InputMethodHighlight.CONVERTED_TEXT) {
 419             index = 2;
 420         } else {
 421             return null;
 422         }
 423         if (highlight.isSelected()) {
 424             index += 1;
 425         }
 426         return highlightStyles[index];
 427     }
 428 
 429     // see sun.awt.im.InputMethodAdapter.supportsBelowTheSpot
 430     protected boolean supportsBelowTheSpot() {
 431         return true;
 432     }
 433 
 434     public void endComposition()
 435     {
 436         //right now the native endCompositionNative() just cancel
 437         //the composition string, maybe a commtting is desired
 438         endCompositionNative(context,
 439             (haveActiveClient() ? COMMIT_INPUT : DISCARD_INPUT));
 440     }
 441 
 442     /**
 443      * @see java.awt.im.spi.InputMethod#setCompositionEnabled(boolean)
 444      */
 445     public void setCompositionEnabled(boolean enable) {
 446         setOpenStatus(context, enable);
 447     }
 448 
 449     /**
 450      * @see java.awt.im.spi.InputMethod#isCompositionEnabled
 451      */
 452     public boolean isCompositionEnabled() {
 453         return getOpenStatus(context);
 454     }
 455 
 456     public void sendInputMethodEvent(int id, long when, String text,
 457                                      int[] clauseBoundary, String[] clauseReading,
 458                                      int[] attributeBoundary, byte[] attributeValue,
 459                                      int commitedTextLength, int caretPos, int visiblePos)
 460     {
 461 
 462         AttributedCharacterIterator iterator = null;
 463 
 464         if (text!=null) {
 465 
 466             // construct AttributedString
 467             AttributedString attrStr = new AttributedString(text);
 468 
 469             // set Language Information
 470             attrStr.addAttribute(Attribute.LANGUAGE,
 471                                             Locale.getDefault(), 0, text.length());
 472 
 473             // set Clause and Reading Information
 474             if (clauseBoundary!=null && clauseReading!=null &&
 475                 clauseReading.length!=0 && clauseBoundary.length==clauseReading.length+1 &&
 476                 clauseBoundary[0]==0 && clauseBoundary[clauseReading.length]==text.length() )
 477             {
 478                 for (int i=0; i<clauseBoundary.length-1; i++) {
 479                     attrStr.addAttribute(Attribute.INPUT_METHOD_SEGMENT,
 480                                             new Annotation(null), clauseBoundary[i], clauseBoundary[i+1]);
 481                     attrStr.addAttribute(Attribute.READING,
 482                                             new Annotation(clauseReading[i]), clauseBoundary[i], clauseBoundary[i+1]);
 483                 }
 484             } else {
 485                 // if (clauseBoundary != null)
 486                 //    System.out.println("Invalid clause information!");
 487 
 488                 attrStr.addAttribute(Attribute.INPUT_METHOD_SEGMENT,
 489                                         new Annotation(null), 0, text.length());
 490                 attrStr.addAttribute(Attribute.READING,
 491                                      new Annotation(""), 0, text.length());
 492             }
 493 
 494             // set Hilight Information
 495             if (attributeBoundary!=null && attributeValue!=null &&
 496                 attributeValue.length!=0 && attributeBoundary.length==attributeValue.length+1 &&
 497                 attributeBoundary[0]==0 && attributeBoundary[attributeValue.length]==text.length() )
 498             {
 499                 for (int i=0; i<attributeBoundary.length-1; i++) {
 500                     InputMethodHighlight highlight;
 501                     switch (attributeValue[i]) {
 502                         case ATTR_TARGET_CONVERTED:
 503                             highlight = InputMethodHighlight.SELECTED_CONVERTED_TEXT_HIGHLIGHT;
 504                             break;
 505                         case ATTR_CONVERTED:
 506                             highlight = InputMethodHighlight.UNSELECTED_CONVERTED_TEXT_HIGHLIGHT;
 507                             break;
 508                         case ATTR_TARGET_NOTCONVERTED:
 509                             highlight = InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT;
 510                             break;
 511                         case ATTR_INPUT:
 512                         case ATTR_INPUT_ERROR:
 513                         default:
 514                             highlight = InputMethodHighlight.UNSELECTED_RAW_TEXT_HIGHLIGHT;
 515                             break;
 516                     }
 517                     attrStr.addAttribute(TextAttribute.INPUT_METHOD_HIGHLIGHT,
 518                                          highlight,
 519                                          attributeBoundary[i], attributeBoundary[i+1]);
 520                 }
 521             } else {
 522                 // if (attributeBoundary != null)
 523                 //    System.out.println("Invalid attribute information!");
 524 
 525                 attrStr.addAttribute(TextAttribute.INPUT_METHOD_HIGHLIGHT,
 526                              InputMethodHighlight.UNSELECTED_CONVERTED_TEXT_HIGHLIGHT,
 527                              0, text.length());
 528             }
 529 
 530             // get iterator
 531             iterator = attrStr.getIterator();
 532 
 533         }
 534 
 535         Component source = getClientComponent();
 536         if (source == null)
 537             return;
 538 
 539         InputMethodEvent event = new InputMethodEvent(source,
 540                                                       id,
 541                                                       when,
 542                                                       iterator,
 543                                                       commitedTextLength,
 544                                                       TextHitInfo.leading(caretPos),
 545                                                       TextHitInfo.leading(visiblePos));
 546         WToolkit.postEvent(WToolkit.targetToAppContext(source), event);
 547     }
 548 
 549     public void inquireCandidatePosition()
 550     {
 551         Component source = getClientComponent();
 552         if (source == null) {
 553             return;
 554         }
 555         // This call should return immediately just to cause
 556         // InputMethodRequests.getTextLocation be called within
 557         // AWT Event thread.  Otherwise, a potential deadlock
 558         // could happen.
 559         Runnable r = new Runnable() {
 560             public void run() {
 561                 int x = 0;
 562                 int y = 0;
 563                 Component client = getClientComponent();
 564 
 565                 if (client != null) {
 566                     if (haveActiveClient()) {
 567                             Rectangle rc = inputContext.getTextLocation(TextHitInfo.leading(0));
 568                             x = rc.x;
 569                             y = rc.y + rc.height;
 570                     } else {
 571                             Point pt = client.getLocationOnScreen();
 572                             Dimension size = client.getSize();
 573                             x = pt.x;
 574                             y = pt.y + size.height;
 575                     }
 576                 }
 577 
 578                 openCandidateWindow(awtFocussedComponentPeer, x, y);
 579             }
 580         };
 581         WToolkit.postEvent(WToolkit.targetToAppContext(source),
 582                            new InvocationEvent(source, r));
 583     }
 584 
 585     // java.awt.Toolkit#getNativeContainer() is not available
 586     //  from this package
 587     private WComponentPeer getNearestNativePeer(Component comp)
 588     {
 589         if (comp==null)     return null;
 590 
 591         ComponentPeer peer = comp.getPeer();
 592         if (peer==null)     return null;
 593 
 594         while (peer instanceof java.awt.peer.LightweightPeer) {
 595             comp = comp.getParent();
 596             if (comp==null) return null;
 597             peer = comp.getPeer();
 598             if (peer==null) return null;
 599         }
 600 
 601         if (peer instanceof WComponentPeer)
 602             return (WComponentPeer)peer;
 603         else
 604             return null;
 605 
 606     }
 607 
 608     private native int createNativeContext();
 609     private native void destroyNativeContext(int context);
 610     private native void enableNativeIME(WComponentPeer peer, int context, boolean useNativeCompWindow);
 611     private native void disableNativeIME(WComponentPeer peer);
 612     private native void handleNativeIMEEvent(WComponentPeer peer, AWTEvent e);
 613     private native void endCompositionNative(int context, boolean flag);
 614     private native void setConversionStatus(int context, int cmode);
 615     private native int  getConversionStatus(int context);
 616     private native void setOpenStatus(int context, boolean flag);
 617     private native boolean getOpenStatus(int context);
 618     private native void setStatusWindowVisible(WComponentPeer peer, boolean visible);
 619     private native String getNativeIMMDescription();
 620     static native Locale getNativeLocale();
 621     static native boolean setNativeLocale(String localeName, boolean onActivate);
 622     private native void openCandidateWindow(WComponentPeer peer, int x, int y);
 623 }