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