Path: blob/master/src/java.desktop/macosx/native/libawt_lwawt/awt/CInputMethod.m
66645 views
/*1* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#import <Cocoa/Cocoa.h>26#include <objc/objc-runtime.h>2728#import "sun_lwawt_macosx_CInputMethod.h"29#import "sun_lwawt_macosx_CInputMethodDescriptor.h"30#import "ThreadUtilities.h"31#import "AWTView.h"32#import "JNIUtilities.h"3334#import <JavaRuntimeSupport/JavaRuntimeSupport.h>3536#define JAVA_LIST @"JAVA_LIST"37#define CURRENT_KB_DESCRIPTION @"CURRENT_KB_DESCRIPTION"3839//40// NOTE: This returns a JNI Local Ref. Any code that calls must call DeleteLocalRef with the return value.41//42static jobject CreateLocaleObjectFromNSString(JNIEnv *env, NSString *name)43{44DECLARE_CLASS_RETURN(jc_localeClass, "java/util/Locale", NULL);45DECLARE_METHOD_RETURN(jm_localeCons, jc_localeClass, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", NULL);46// Break apart the string into its components.47// First, duplicate the NSString into a C string, since we're going to modify it.48char * language = strdup([name UTF8String]);49char * country;50char * variant;5152// Convert _ to NULL -- this gives us three null terminated strings in place.53for (country = language; *country != '_' && *country != '\0'; country++);54if (*country == '_') {55*country++ = '\0';56for (variant = country; *variant != '_' && *variant != '\0'; variant++);57if (*variant == '_') {58*variant++ = '\0';59}60} else {61variant = country;62}6364// Create the java.util.Locale object65jobject localeObj = NULL;66jobject langObj = (*env)->NewStringUTF(env, language);67if (langObj != NULL) {68jobject ctryObj = (*env)->NewStringUTF(env, country);69if(ctryObj != NULL) {70jobject vrntObj = (*env)->NewStringUTF(env, variant);71if (vrntObj != NULL) {72localeObj = (*env)->NewObject(env, jc_localeClass, jm_localeCons,langObj, ctryObj,73vrntObj);74CHECK_EXCEPTION();75(*env)->DeleteLocalRef(env, vrntObj);76}77(*env)->DeleteLocalRef(env, ctryObj);78}79(*env)->DeleteLocalRef(env, langObj);80}81// Clean up and return.82free(language);83return localeObj;84}8586static id inputMethodController = nil;8788static void initializeInputMethodController() {89static BOOL checkedJRSInputMethodController = NO;90if (!checkedJRSInputMethodController && (inputMethodController == nil)) {91id jrsInputMethodController = objc_lookUpClass("JRSInputMethodController");92if (jrsInputMethodController != nil) {93inputMethodController = [jrsInputMethodController performSelector:@selector(controller)];94}95checkedJRSInputMethodController = YES;96}97}9899100@interface CInputMethod : NSObject {}101@end102103@implementation CInputMethod104105+ (void) setKeyboardLayout:(NSString *)theLocale106{107AWT_ASSERT_APPKIT_THREAD;108if (!inputMethodController) return;109110[inputMethodController performSelector:@selector(setCurrentInputMethodForLocale) withObject:theLocale];111}112113+ (void) _nativeNotifyPeerWithView:(AWTView *)view inputMethod:(jobject) inputMethod {114AWT_ASSERT_APPKIT_THREAD;115116if (!view) return;117[view setInputMethod:inputMethod]; // inputMethod is a GlobalRef or null to disable.118}119120+ (void) _nativeEndComposition:(AWTView *)view {121if (view == nil) return;122123[view abandonInput];124}125126127@end128129/*130* Class: sun_lwawt_macosx_CInputMethod131* Method: nativeInit132* Signature: ();133*/134JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CInputMethod_nativeInit135(JNIEnv *env, jclass klass)136{137initializeInputMethodController();138}139140/*141* Class: sun_lwawt_macosx_CInputMethod142* Method: nativeGetCurrentInputMethodInfo143* Signature: ()Ljava/lang/String;144*/145JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CInputMethod_nativeGetCurrentInputMethodInfo146(JNIEnv *env, jclass klass)147{148if (!inputMethodController) return NULL;149jobject returnValue = 0;150__block NSString *keyboardInfo = NULL;151JNI_COCOA_ENTER(env);152153[ThreadUtilities performOnMainThreadWaiting:YES block:^(){154keyboardInfo = [inputMethodController performSelector:@selector(currentInputMethodName)];155[keyboardInfo retain];156}];157158if (keyboardInfo == nil) return NULL;159returnValue = NSStringToJavaString(env, keyboardInfo);160[keyboardInfo release];161162JNI_COCOA_EXIT(env);163return returnValue;164}165166/*167* Class: sun_lwawt_macosx_CInputMethod168* Method: nativeActivate169* Signature: (JLsun/lwawt/macosx/CInputMethod;)V170*/171JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CInputMethod_nativeNotifyPeer172(JNIEnv *env, jobject this, jlong nativePeer, jobject inputMethod)173{174JNI_COCOA_ENTER(env);175AWTView *view = (AWTView *)jlong_to_ptr(nativePeer);176jobject inputMethodRef = (*env)->NewGlobalRef(env, inputMethod);177[ThreadUtilities performOnMainThreadWaiting:NO block:^(){178[CInputMethod _nativeNotifyPeerWithView:view inputMethod:inputMethodRef];179}];180181JNI_COCOA_EXIT(env);182183}184185/*186* Class: sun_lwawt_macosx_CInputMethod187* Method: nativeEndComposition188* Signature: (J)V189*/190JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CInputMethod_nativeEndComposition191(JNIEnv *env, jobject this, jlong nativePeer)192{193JNI_COCOA_ENTER(env);194AWTView *view = (AWTView *)jlong_to_ptr(nativePeer);195196[ThreadUtilities performOnMainThreadWaiting:NO block:^(){197[CInputMethod _nativeEndComposition:view];198}];199200JNI_COCOA_EXIT(env);201}202203/*204* Class: sun_lwawt_macosx_CInputMethod205* Method: getNativeLocale206* Signature: ()Ljava/util/Locale;207*/208JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CInputMethod_getNativeLocale209(JNIEnv *env, jobject this)210{211if (!inputMethodController) return NULL;212jobject returnValue = 0;213__block NSString *isoAbbreviation;214JNI_COCOA_ENTER(env);215216[ThreadUtilities performOnMainThreadWaiting:YES block:^(){217isoAbbreviation = (NSString *) [inputMethodController performSelector:@selector(currentInputMethodLocale)];218[isoAbbreviation retain];219}];220221if (isoAbbreviation == nil) return NULL;222223static NSString *sLastKeyboardStr = nil;224static jobject sLastKeyboardLocaleObj = NULL;225226if (![isoAbbreviation isEqualTo:sLastKeyboardStr]) {227[sLastKeyboardStr release];228sLastKeyboardStr = [isoAbbreviation retain];229jobject localObj = CreateLocaleObjectFromNSString(env, isoAbbreviation);230[isoAbbreviation release];231232if (sLastKeyboardLocaleObj) {233(*env)->DeleteGlobalRef(env, sLastKeyboardLocaleObj);234sLastKeyboardLocaleObj = NULL;235}236if (localObj != NULL) {237sLastKeyboardLocaleObj = (*env)->NewGlobalRef(env, localObj);238(*env)->DeleteLocalRef(env, localObj);239}240}241242returnValue = sLastKeyboardLocaleObj;243244JNI_COCOA_EXIT(env);245return returnValue;246}247248249/*250* Class: sun_lwawt_macosx_CInputMethod251* Method: setNativeLocale252* Signature: (Ljava/lang/String;Z)Z253*/254JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CInputMethod_setNativeLocale255(JNIEnv *env, jobject this, jstring locale, jboolean isActivating)256{257JNI_COCOA_ENTER(env);258NSString *localeStr = JavaStringToNSString(env, locale);259[localeStr retain];260261[ThreadUtilities performOnMainThreadWaiting:YES block:^(){262[CInputMethod setKeyboardLayout:localeStr];263}];264265[localeStr release];266JNI_COCOA_EXIT(env);267return JNI_TRUE;268}269270/*271* Class: sun_lwawt_macosx_CInputMethodDescriptor272* Method: nativeInit273* Signature: ();274*/275JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CInputMethodDescriptor_nativeInit276(JNIEnv *env, jclass klass)277{278initializeInputMethodController();279}280281/*282* Class: sun_lwawt_macosx_CInputMethodDescriptor283* Method: nativeGetAvailableLocales284* Signature: ()[Ljava/util/Locale;285*/286JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CInputMethodDescriptor_nativeGetAvailableLocales287(JNIEnv *env, jclass klass)288{289DECLARE_CLASS_RETURN(jc_arrayListClass, "java/util/ArrayList", NULL);290DECLARE_METHOD_RETURN(jm_arrayListCons, jc_arrayListClass, "<init>", "()V", NULL);291DECLARE_METHOD_RETURN(jm_listAdd, jc_arrayListClass, "add", "(Ljava/lang/Object;)Z", NULL);292DECLARE_METHOD_RETURN(jm_listContains, jc_arrayListClass, "contains", "(Ljava/lang/Object;)Z", NULL);293294if (!inputMethodController) return NULL;295jobject returnValue = 0;296297__block NSArray *selectableArray = nil;298JNI_COCOA_ENTER(env);299300[ThreadUtilities performOnMainThreadWaiting:YES block:^(){301selectableArray = (NSArray *)[inputMethodController performSelector:@selector(availableInputMethodLocales)];302[selectableArray retain];303}];304305if (selectableArray == nil) return NULL;306307// Create an ArrayList to return back to the caller.308returnValue = (*env)->NewObject(env, jc_arrayListClass, jm_arrayListCons);309CHECK_EXCEPTION_NULL_RETURN(returnValue, NULL);310311for(NSString *locale in selectableArray) {312jobject localeObj = CreateLocaleObjectFromNSString(env, locale);313if (localeObj == NULL) {314break;315}316317if ((*env)->CallBooleanMethod(env, returnValue, jm_listContains, localeObj) == JNI_FALSE) {318if ((*env)->ExceptionOccurred(env)) (*env)->ExceptionClear(env);319(*env)->CallBooleanMethod(env, returnValue, jm_listAdd, localeObj);320}321if ((*env)->ExceptionOccurred(env)) (*env)->ExceptionClear(env);322323(*env)->DeleteLocalRef(env, localeObj);324}325[selectableArray release];326JNI_COCOA_EXIT(env);327return returnValue;328}329330331332