Path: blob/master/src/java.desktop/macosx/native/libawt_lwawt/awt/CInputMethod.m
41152 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;117if (!inputMethod) return;118119[view setInputMethod:inputMethod]; // inputMethod is a GlobalRef120}121122+ (void) _nativeEndComposition:(AWTView *)view {123if (view == nil) return;124125[view abandonInput];126}127128129@end130131/*132* Class: sun_lwawt_macosx_CInputMethod133* Method: nativeInit134* Signature: ();135*/136JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CInputMethod_nativeInit137(JNIEnv *env, jclass klass)138{139initializeInputMethodController();140}141142/*143* Class: sun_lwawt_macosx_CInputMethod144* Method: nativeGetCurrentInputMethodInfo145* Signature: ()Ljava/lang/String;146*/147JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CInputMethod_nativeGetCurrentInputMethodInfo148(JNIEnv *env, jclass klass)149{150if (!inputMethodController) return NULL;151jobject returnValue = 0;152__block NSString *keyboardInfo = NULL;153JNI_COCOA_ENTER(env);154155[ThreadUtilities performOnMainThreadWaiting:YES block:^(){156keyboardInfo = [inputMethodController performSelector:@selector(currentInputMethodName)];157[keyboardInfo retain];158}];159160if (keyboardInfo == nil) return NULL;161returnValue = NSStringToJavaString(env, keyboardInfo);162[keyboardInfo release];163164JNI_COCOA_EXIT(env);165return returnValue;166}167168/*169* Class: sun_lwawt_macosx_CInputMethod170* Method: nativeActivate171* Signature: (JLsun/lwawt/macosx/CInputMethod;)V172*/173JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CInputMethod_nativeNotifyPeer174(JNIEnv *env, jobject this, jlong nativePeer, jobject inputMethod)175{176JNI_COCOA_ENTER(env);177AWTView *view = (AWTView *)jlong_to_ptr(nativePeer);178jobject inputMethodRef = (*env)->NewGlobalRef(env, inputMethod);179[ThreadUtilities performOnMainThreadWaiting:NO block:^(){180[CInputMethod _nativeNotifyPeerWithView:view inputMethod:inputMethodRef];181}];182183JNI_COCOA_EXIT(env);184185}186187/*188* Class: sun_lwawt_macosx_CInputMethod189* Method: nativeEndComposition190* Signature: (J)V191*/192JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CInputMethod_nativeEndComposition193(JNIEnv *env, jobject this, jlong nativePeer)194{195JNI_COCOA_ENTER(env);196AWTView *view = (AWTView *)jlong_to_ptr(nativePeer);197198[ThreadUtilities performOnMainThreadWaiting:NO block:^(){199[CInputMethod _nativeEndComposition:view];200}];201202JNI_COCOA_EXIT(env);203}204205/*206* Class: sun_lwawt_macosx_CInputMethod207* Method: getNativeLocale208* Signature: ()Ljava/util/Locale;209*/210JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CInputMethod_getNativeLocale211(JNIEnv *env, jobject this)212{213if (!inputMethodController) return NULL;214jobject returnValue = 0;215__block NSString *isoAbbreviation;216JNI_COCOA_ENTER(env);217218[ThreadUtilities performOnMainThreadWaiting:YES block:^(){219isoAbbreviation = (NSString *) [inputMethodController performSelector:@selector(currentInputMethodLocale)];220[isoAbbreviation retain];221}];222223if (isoAbbreviation == nil) return NULL;224225static NSString *sLastKeyboardStr = nil;226static jobject sLastKeyboardLocaleObj = NULL;227228if (![isoAbbreviation isEqualTo:sLastKeyboardStr]) {229[sLastKeyboardStr release];230sLastKeyboardStr = [isoAbbreviation retain];231jobject localObj = CreateLocaleObjectFromNSString(env, isoAbbreviation);232[isoAbbreviation release];233234if (sLastKeyboardLocaleObj) {235(*env)->DeleteGlobalRef(env, sLastKeyboardLocaleObj);236sLastKeyboardLocaleObj = NULL;237}238if (localObj != NULL) {239sLastKeyboardLocaleObj = (*env)->NewGlobalRef(env, localObj);240(*env)->DeleteLocalRef(env, localObj);241}242}243244returnValue = sLastKeyboardLocaleObj;245246JNI_COCOA_EXIT(env);247return returnValue;248}249250251/*252* Class: sun_lwawt_macosx_CInputMethod253* Method: setNativeLocale254* Signature: (Ljava/lang/String;Z)Z255*/256JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CInputMethod_setNativeLocale257(JNIEnv *env, jobject this, jstring locale, jboolean isActivating)258{259JNI_COCOA_ENTER(env);260NSString *localeStr = JavaStringToNSString(env, locale);261[localeStr retain];262263[ThreadUtilities performOnMainThreadWaiting:YES block:^(){264[CInputMethod setKeyboardLayout:localeStr];265}];266267[localeStr release];268JNI_COCOA_EXIT(env);269return JNI_TRUE;270}271272/*273* Class: sun_lwawt_macosx_CInputMethodDescriptor274* Method: nativeInit275* Signature: ();276*/277JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CInputMethodDescriptor_nativeInit278(JNIEnv *env, jclass klass)279{280initializeInputMethodController();281}282283/*284* Class: sun_lwawt_macosx_CInputMethodDescriptor285* Method: nativeGetAvailableLocales286* Signature: ()[Ljava/util/Locale;287*/288JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CInputMethodDescriptor_nativeGetAvailableLocales289(JNIEnv *env, jclass klass)290{291DECLARE_CLASS_RETURN(jc_arrayListClass, "java/util/ArrayList", NULL);292DECLARE_METHOD_RETURN(jm_arrayListCons, jc_arrayListClass, "<init>", "()V", NULL);293DECLARE_METHOD_RETURN(jm_listAdd, jc_arrayListClass, "add", "(Ljava/lang/Object;)Z", NULL);294DECLARE_METHOD_RETURN(jm_listContains, jc_arrayListClass, "contains", "(Ljava/lang/Object;)Z", NULL);295296if (!inputMethodController) return NULL;297jobject returnValue = 0;298299__block NSArray *selectableArray = nil;300JNI_COCOA_ENTER(env);301302[ThreadUtilities performOnMainThreadWaiting:YES block:^(){303selectableArray = (NSArray *)[inputMethodController performSelector:@selector(availableInputMethodLocales)];304[selectableArray retain];305}];306307if (selectableArray == nil) return NULL;308309// Create an ArrayList to return back to the caller.310returnValue = (*env)->NewObject(env, jc_arrayListClass, jm_arrayListCons);311CHECK_EXCEPTION_NULL_RETURN(returnValue, NULL);312313for(NSString *locale in selectableArray) {314jobject localeObj = CreateLocaleObjectFromNSString(env, locale);315if (localeObj == NULL) {316break;317}318319if ((*env)->CallBooleanMethod(env, returnValue, jm_listContains, localeObj) == JNI_FALSE) {320if ((*env)->ExceptionOccurred(env)) (*env)->ExceptionClear(env);321(*env)->CallBooleanMethod(env, returnValue, jm_listAdd, localeObj);322}323if ((*env)->ExceptionOccurred(env)) (*env)->ExceptionClear(env);324325(*env)->DeleteLocalRef(env, localeObj);326}327[selectableArray release];328JNI_COCOA_EXIT(env);329return returnValue;330}331332333334