Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/awt/awt_InputMethod.c
32287 views
/*1* Copyright (c) 1997, 2018, 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#ifdef HEADLESS26#error This file should not be included in headless library27#endif2829#include <stdio.h>30#include <stdlib.h>31#include <X11/Xlib.h>32#include <X11/keysym.h>33#include <sys/time.h>3435#include "awt.h"36#include "awt_p.h"3738#include <sun_awt_X11InputMethod.h>39#include <sun_awt_X11_XInputMethod.h>4041#define THROW_OUT_OF_MEMORY_ERROR() \42JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL)43#define SETARG(name, value) XtSetArg(args[argc], name, value); argc++4445struct X11InputMethodIDs {46jfieldID pData;47} x11InputMethodIDs;4849static void PreeditStartCallback(XIC, XPointer, XPointer);50static void PreeditDoneCallback(XIC, XPointer, XPointer);51static void PreeditDrawCallback(XIC, XPointer,52XIMPreeditDrawCallbackStruct *);53static void PreeditCaretCallback(XIC, XPointer,54XIMPreeditCaretCallbackStruct *);55#if defined(__linux__) || defined(MACOSX)56static void StatusStartCallback(XIC, XPointer, XPointer);57static void StatusDoneCallback(XIC, XPointer, XPointer);58static void StatusDrawCallback(XIC, XPointer,59XIMStatusDrawCallbackStruct *);60#endif6162#define ROOT_WINDOW_STYLES (XIMPreeditNothing | XIMStatusNothing)63#define NO_STYLES (XIMPreeditNone | XIMStatusNone)6465#define PreeditStartIndex 066#define PreeditDoneIndex 167#define PreeditDrawIndex 268#define PreeditCaretIndex 369#if defined(__linux__) || defined(MACOSX)70#define StatusStartIndex 471#define StatusDoneIndex 572#define StatusDrawIndex 673#define NCALLBACKS 774#else75#define NCALLBACKS 476#endif7778/*79* Callback function pointers: the order has to match the *Index80* values above.81*/82static XIMProc callback_funcs[NCALLBACKS] = {83(XIMProc)PreeditStartCallback,84(XIMProc)PreeditDoneCallback,85(XIMProc)PreeditDrawCallback,86(XIMProc)PreeditCaretCallback,87#if defined(__linux__) || defined(MACOSX)88(XIMProc)StatusStartCallback,89(XIMProc)StatusDoneCallback,90(XIMProc)StatusDrawCallback,91#endif92};9394#if defined(__linux__) || defined(MACOSX)95#define MAX_STATUS_LEN 10096typedef struct {97Window w; /*status window id */98Window root; /*the root window id */99Window parent; /*parent shell window */100int x, y; /*parent's upperleft position */101int width, height; /*parent's width, height */102GC lightGC; /*gc for light border */103GC dimGC; /*gc for dim border */104GC bgGC; /*normal painting */105GC fgGC; /*normal painting */106int statusW, statusH; /*status window's w, h */107int rootW, rootH; /*root window's w, h */108int bWidth; /*border width */109char status[MAX_STATUS_LEN]; /*status text */110XFontSet fontset; /*fontset for drawing */111int off_x, off_y;112Bool on; /*if the status window on*/113} StatusWindow;114#endif115116/*117* X11InputMethodData keeps per X11InputMethod instance information. A pointer118* to this data structure is kept in an X11InputMethod object (pData).119*/120typedef struct _X11InputMethodData {121XIC current_ic; /* current X Input Context */122XIC ic_active; /* X Input Context for active clients */123XIC ic_passive; /* X Input Context for passive clients */124XIMCallback *callbacks; /* callback parameters */125jobject x11inputmethod; /* global ref to X11InputMethod instance */126/* associated with the XIC */127#if defined(__linux__) || defined(MACOSX)128StatusWindow *statusWindow; /* our own status window */129#endif130char *lookup_buf; /* buffer used for XmbLookupString */131int lookup_buf_len; /* lookup buffer size in bytes */132} X11InputMethodData;133134/*135* When XIC is created, a global reference is created for136* sun.awt.X11InputMethod object so that it could be used by the XIM callback137* functions. This could be a dangerous thing to do when the original138* X11InputMethod object is garbage collected and as a result,139* destroyX11InputMethodData is called to delete the global reference.140* If any XIM callback function still holds and uses the "already deleted"141* global reference, disaster is going to happen. So we have to maintain142* a list for these global references which is consulted first when the143* callback functions or any function tries to use "currentX11InputMethodObject"144* which always refers to the global reference try to use it.145*146*/147typedef struct _X11InputMethodGRefNode {148jobject inputMethodGRef;149struct _X11InputMethodGRefNode* next;150} X11InputMethodGRefNode;151152X11InputMethodGRefNode *x11InputMethodGRefListHead = NULL;153154/* reference to the current X11InputMethod instance, it is always155point to the global reference to the X11InputMethodObject since156it could be referenced by different threads. */157jobject currentX11InputMethodInstance = NULL;158159Window currentFocusWindow = 0; /* current window that has focus for input160method. (the best place to put this161information should be162currentX11InputMethodInstance's pData) */163static XIM X11im = NULL;164Display * dpy = NULL;165166#define GetJNIEnv() (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2)167168static void DestroyXIMCallback(XIM, XPointer, XPointer);169static void OpenXIMCallback(Display *, XPointer, XPointer);170/* Solaris XIM Extention */171#define XNCommitStringCallback "commitStringCallback"172static void CommitStringCallback(XIC, XPointer, XPointer);173174static X11InputMethodData * getX11InputMethodData(JNIEnv *, jobject);175static void setX11InputMethodData(JNIEnv *, jobject, X11InputMethodData *);176static void destroyX11InputMethodData(JNIEnv *, X11InputMethodData *);177static void freeX11InputMethodData(JNIEnv *, X11InputMethodData *);178179#ifdef __solaris__180/* Prototype for this function is missing in Solaris X11R6 Xlib.h */181extern char *XSetIMValues(182#if NeedVarargsPrototypes183XIM /* im */, ...184#endif185);186#endif187188/*189* This function is stolen from /src/solaris/hpi/src/system_md.c190* It is used in setting the time in Java-level InputEvents191*/192jlong193awt_util_nowMillisUTC()194{195struct timeval t;196gettimeofday(&t, NULL);197return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000);198}199200/*201* Converts the wchar_t string to a multi-byte string calling wcstombs(). A202* buffer is allocated by malloc() to store the multi-byte string. NULL is203* returned if the given wchar_t string pointer is NULL or buffer allocation is204* failed.205*/206static char *207wcstombsdmp(wchar_t *wcs, int len)208{209size_t n;210char *mbs;211212if (wcs == NULL)213return NULL;214215n = len*MB_CUR_MAX + 1;216217mbs = (char *) malloc(n * sizeof(char));218if (mbs == NULL) {219THROW_OUT_OF_MEMORY_ERROR();220return NULL;221}222223/* TODO: check return values... Handle invalid characters properly... */224if (wcstombs(mbs, wcs, n) == (size_t)-1)225return NULL;226227return mbs;228}229230/*231* Returns True if the global reference is still in the list,232* otherwise False.233*/234static Bool isX11InputMethodGRefInList(jobject imGRef) {235X11InputMethodGRefNode *pX11InputMethodGRef = x11InputMethodGRefListHead;236237if (imGRef == NULL) {238return False;239}240241while (pX11InputMethodGRef != NULL) {242if (pX11InputMethodGRef->inputMethodGRef == imGRef) {243return True;244}245pX11InputMethodGRef = pX11InputMethodGRef->next;246}247248return False;249}250251/*252* Add the new created global reference to the list.253*/254static void addToX11InputMethodGRefList(jobject newX11InputMethodGRef) {255X11InputMethodGRefNode *newNode = NULL;256257if (newX11InputMethodGRef == NULL ||258isX11InputMethodGRefInList(newX11InputMethodGRef)) {259return;260}261262newNode = (X11InputMethodGRefNode *)malloc(sizeof(X11InputMethodGRefNode));263264if (newNode == NULL) {265return;266} else {267newNode->inputMethodGRef = newX11InputMethodGRef;268newNode->next = x11InputMethodGRefListHead;269x11InputMethodGRefListHead = newNode;270}271}272273/*274* Remove the global reference from the list.275*/276static void removeX11InputMethodGRefFromList(jobject x11InputMethodGRef) {277X11InputMethodGRefNode *pX11InputMethodGRef = NULL;278X11InputMethodGRefNode *cX11InputMethodGRef = x11InputMethodGRefListHead;279280if (x11InputMethodGRefListHead == NULL ||281x11InputMethodGRef == NULL) {282return;283}284285/* cX11InputMethodGRef always refers to the current node while286pX11InputMethodGRef refers to the previous node.287*/288while (cX11InputMethodGRef != NULL) {289if (cX11InputMethodGRef->inputMethodGRef == x11InputMethodGRef) {290break;291}292pX11InputMethodGRef = cX11InputMethodGRef;293cX11InputMethodGRef = cX11InputMethodGRef->next;294}295296if (cX11InputMethodGRef == NULL) {297return; /* Not found. */298}299300if (cX11InputMethodGRef == x11InputMethodGRefListHead) {301x11InputMethodGRefListHead = x11InputMethodGRefListHead->next;302} else {303pX11InputMethodGRef->next = cX11InputMethodGRef->next;304}305free(cX11InputMethodGRef);306307return;308}309310311static X11InputMethodData * getX11InputMethodData(JNIEnv * env, jobject imInstance) {312X11InputMethodData *pX11IMData =313(X11InputMethodData *)JNU_GetLongFieldAsPtr(env, imInstance, x11InputMethodIDs.pData);314315/*316* In case the XIM server was killed somehow, reset X11InputMethodData.317*/318if (X11im == NULL && pX11IMData != NULL) {319JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,320"flushText",321"()V");322JNU_CHECK_EXCEPTION_RETURN(env, NULL);323/* IMPORTANT:324The order of the following calls is critical since "imInstance" may325point to the global reference itself, if "freeX11InputMethodData" is called326first, the global reference will be destroyed and "setX11InputMethodData"327will in fact fail silently. So pX11IMData will not be set to NULL.328This could make the original java object refers to a deleted pX11IMData329object.330*/331setX11InputMethodData(env, imInstance, NULL);332freeX11InputMethodData(env, pX11IMData);333pX11IMData = NULL;334}335336return pX11IMData;337}338339static void setX11InputMethodData(JNIEnv * env, jobject imInstance, X11InputMethodData *pX11IMData) {340JNU_SetLongFieldFromPtr(env, imInstance, x11InputMethodIDs.pData, pX11IMData);341}342343/* this function should be called within AWT_LOCK() */344static void345destroyX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData)346{347/*348* Destroy XICs349*/350if (pX11IMData == NULL) {351return;352}353354if (pX11IMData->ic_active != (XIC)0) {355XUnsetICFocus(pX11IMData->ic_active);356XDestroyIC(pX11IMData->ic_active);357if (pX11IMData->ic_active != pX11IMData->ic_passive) {358if (pX11IMData->ic_passive != (XIC)0) {359XUnsetICFocus(pX11IMData->ic_passive);360XDestroyIC(pX11IMData->ic_passive);361}362pX11IMData->ic_passive = (XIC)0;363pX11IMData->current_ic = (XIC)0;364}365}366367freeX11InputMethodData(env, pX11IMData);368}369370static void371freeX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData)372{373#if defined(__linux__) || defined(MACOSX)374if (pX11IMData->statusWindow != NULL){375StatusWindow *sw = pX11IMData->statusWindow;376XFreeGC(awt_display, sw->lightGC);377XFreeGC(awt_display, sw->dimGC);378XFreeGC(awt_display, sw->bgGC);379XFreeGC(awt_display, sw->fgGC);380if (sw->fontset != NULL) {381XFreeFontSet(awt_display, sw->fontset);382}383XDestroyWindow(awt_display, sw->w);384free((void*)sw);385}386#endif387388if (pX11IMData->callbacks)389free((void *)pX11IMData->callbacks);390391if (env) {392/* Remove the global reference from the list, so that393the callback function or whoever refers to it could know.394*/395removeX11InputMethodGRefFromList(pX11IMData->x11inputmethod);396(*env)->DeleteGlobalRef(env, pX11IMData->x11inputmethod);397}398399if (pX11IMData->lookup_buf) {400free((void *)pX11IMData->lookup_buf);401}402403free((void *)pX11IMData);404}405406/*407* Sets or unsets the focus to the given XIC.408*/409static void410setXICFocus(XIC ic, unsigned short req)411{412if (ic == NULL) {413(void)fprintf(stderr, "Couldn't find X Input Context\n");414return;415}416if (req == 1)417XSetICFocus(ic);418else419XUnsetICFocus(ic);420}421422/*423* Sets the focus window to the given XIC.424*/425static void426setXICWindowFocus(XIC ic, Window w)427{428if (ic == NULL) {429(void)fprintf(stderr, "Couldn't find X Input Context\n");430return;431}432(void) XSetICValues(ic, XNFocusWindow, w, NULL);433}434435/*436* Invokes XmbLookupString() to get something from the XIM. It invokes437* X11InputMethod.dispatchCommittedText() if XmbLookupString() returns438* committed text. This function is called from handleKeyEvent in canvas.c and439* it's under the Motif event loop thread context.440*441* Buffer usage: There is a bug in XFree86-4.3.0 XmbLookupString implementation,442* where it never returns XBufferOverflow. We need to allocate the initial lookup buffer443* big enough, so that the possibility that user encounters this problem is relatively444* small. When this bug gets fixed, we can make the initial buffer size smaller.445* Note that XmbLookupString() sometimes produces a non-null-terminated string.446*447* Returns True when there is a keysym value to be handled.448*/449#define INITIAL_LOOKUP_BUF_SIZE 512450451Boolean452awt_x11inputmethod_lookupString(XKeyPressedEvent *event, KeySym *keysymp)453{454JNIEnv *env = GetJNIEnv();455X11InputMethodData *pX11IMData = NULL;456KeySym keysym = NoSymbol;457Status status;458int mblen;459jstring javastr;460XIC ic;461Boolean result = True;462static Boolean composing = False;463464/*465printf("lookupString: entering...\n");466*/467468if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) {469currentX11InputMethodInstance = NULL;470return False;471}472473pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance);474475if (pX11IMData == NULL) {476#if defined(__linux__) || defined(MACOSX)477return False;478#else479return result;480#endif481}482483if ((ic = pX11IMData->current_ic) == (XIC)0){484#if defined(__linux__) || defined(MACOSX)485return False;486#else487return result;488#endif489}490491/* allocate the lookup buffer at the first invocation */492if (pX11IMData->lookup_buf_len == 0) {493pX11IMData->lookup_buf = (char *)malloc(INITIAL_LOOKUP_BUF_SIZE);494if (pX11IMData->lookup_buf == NULL) {495THROW_OUT_OF_MEMORY_ERROR();496return result;497}498pX11IMData->lookup_buf_len = INITIAL_LOOKUP_BUF_SIZE;499}500501mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf,502pX11IMData->lookup_buf_len - 1, &keysym, &status);503504/*505* In case of overflow, a buffer is allocated and it retries506* XmbLookupString().507*/508if (status == XBufferOverflow) {509free((void *)pX11IMData->lookup_buf);510pX11IMData->lookup_buf_len = 0;511pX11IMData->lookup_buf = (char *)malloc(mblen + 1);512if (pX11IMData->lookup_buf == NULL) {513THROW_OUT_OF_MEMORY_ERROR();514return result;515}516pX11IMData->lookup_buf_len = mblen + 1;517mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf,518pX11IMData->lookup_buf_len - 1, &keysym, &status);519}520pX11IMData->lookup_buf[mblen] = 0;521522/* Get keysym without taking modifiers into account first to map523* to AWT keyCode table.524*/525switch (status) {526case XLookupBoth:527if (!composing) {528if (event->keycode != 0) {529*keysymp = keysym;530result = False;531break;532}533}534composing = False;535/*FALLTHRU*/536case XLookupChars:537/*538printf("lookupString: status=XLookupChars, type=%d, state=%x, keycode=%x, keysym=%x\n",539event->type, event->state, event->keycode, keysym);540*/541javastr = JNU_NewStringPlatform(env, (const char *)pX11IMData->lookup_buf);542if (javastr != NULL) {543JNU_CallMethodByName(env, NULL,544currentX11InputMethodInstance,545"dispatchCommittedText",546"(Ljava/lang/String;J)V",547javastr,548event->time);549}550break;551552case XLookupKeySym:553/*554printf("lookupString: status=XLookupKeySym, type=%d, state=%x, keycode=%x, keysym=%x\n",555event->type, event->state, event->keycode, keysym);556*/557if (keysym == XK_Multi_key)558composing = True;559if (! composing) {560*keysymp = keysym;561result = False;562}563break;564565case XLookupNone:566/*567printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n",568event->type, event->state, event->keycode, keysym);569*/570break;571}572573return result;574}575576#if defined(__linux__) || defined(MACOSX)577static StatusWindow *createStatusWindow(578Window parent) {579StatusWindow *statusWindow;580XSetWindowAttributes attrib;581unsigned long attribmask;582Window containerWindow;583Window status;584Window child;585XWindowAttributes xwa;586XWindowAttributes xxwa;587/* Variable for XCreateFontSet()*/588char **mclr;589int mccr = 0;590char *dsr;591Pixel bg, fg, light, dim;592int x, y, off_x, off_y, xx, yy;593unsigned int w, h, bw, depth;594XGCValues values;595unsigned long valuemask = 0; /*ignore XGCvalue and use defaults*/596int screen = 0;597int i;598AwtGraphicsConfigDataPtr adata;599extern int awt_numScreens;600/*hardcode the size right now, should get the size base on font*/601int width=80, height=22;602Window rootWindow;603Window *ignoreWindowPtr;604unsigned int ignoreUnit;605606XGetGeometry(dpy, parent, &rootWindow, &x, &y, &w, &h, &bw, &depth);607608attrib.override_redirect = True;609attribmask = CWOverrideRedirect;610for (i = 0; i < awt_numScreens; i++) {611if (RootWindow(dpy, i) == rootWindow) {612screen = i;613break;614}615}616adata = getDefaultConfig(screen);617bg = adata->AwtColorMatch(255, 255, 255, adata);618fg = adata->AwtColorMatch(0, 0, 0, adata);619light = adata->AwtColorMatch(195, 195, 195, adata);620dim = adata->AwtColorMatch(128, 128, 128, adata);621622XGetWindowAttributes(dpy, parent, &xwa);623bw = 2; /*xwa.border_width does not have the correct value*/624625/*compare the size difference between parent container626and shell widget, the diff should be the border frame627and title bar height (?)*/628629XQueryTree( dpy,630parent,631&rootWindow,632&containerWindow,633&ignoreWindowPtr,634&ignoreUnit);635XGetWindowAttributes(dpy, containerWindow, &xxwa);636637off_x = (xxwa.width - xwa.width) / 2;638off_y = xxwa.height - xwa.height - off_x; /*it's magic:-) */639640/*get the size of root window*/641XGetWindowAttributes(dpy, rootWindow, &xxwa);642643XTranslateCoordinates(dpy,644parent, xwa.root,645xwa.x, xwa.y,646&x, &y,647&child);648xx = x - off_x;649yy = y + xwa.height - off_y;650if (xx < 0 ){651xx = 0;652}653if (xx + width > xxwa.width){654xx = xxwa.width - width;655}656if (yy + height > xxwa.height){657yy = xxwa.height - height;658}659660status = XCreateWindow(dpy,661xwa.root,662xx, yy,663width, height,6640,665xwa.depth,666InputOutput,667adata->awt_visInfo.visual,668attribmask, &attrib);669XSelectInput(dpy, status,670ExposureMask | StructureNotifyMask | EnterWindowMask |671LeaveWindowMask | VisibilityChangeMask);672statusWindow = (StatusWindow*) calloc(1, sizeof(StatusWindow));673if (statusWindow == NULL){674THROW_OUT_OF_MEMORY_ERROR();675return NULL;676}677statusWindow->w = status;678//12-point font679statusWindow->fontset = XCreateFontSet(dpy,680"-*-*-medium-r-normal-*-*-120-*-*-*-*",681&mclr, &mccr, &dsr);682/* In case we didn't find the font set, release the list of missing characters */683if (mccr > 0) {684XFreeStringList(mclr);685}686statusWindow->parent = parent;687statusWindow->on = False;688statusWindow->x = x;689statusWindow->y = y;690statusWindow->width = xwa.width;691statusWindow->height = xwa.height;692statusWindow->off_x = off_x;693statusWindow->off_y = off_y;694statusWindow->bWidth = bw;695statusWindow->statusH = height;696statusWindow->statusW = width;697statusWindow->rootH = xxwa.height;698statusWindow->rootW = xxwa.width;699statusWindow->lightGC = XCreateGC(dpy, status, valuemask, &values);700XSetForeground(dpy, statusWindow->lightGC, light);701statusWindow->dimGC = XCreateGC(dpy, status, valuemask, &values);702XSetForeground(dpy, statusWindow->dimGC, dim);703statusWindow->fgGC = XCreateGC(dpy, status, valuemask, &values);704XSetForeground(dpy, statusWindow->fgGC, fg);705statusWindow->bgGC = XCreateGC(dpy, status, valuemask, &values);706XSetForeground(dpy, statusWindow->bgGC, bg);707return statusWindow;708}709710/* This method is to turn off or turn on the status window. */711static void onoffStatusWindow(X11InputMethodData* pX11IMData,712Window parent,713Bool ON){714XWindowAttributes xwa;715Window child;716int x, y;717StatusWindow *statusWindow = NULL;718719if (NULL == currentX11InputMethodInstance ||720NULL == pX11IMData ||721NULL == (statusWindow = pX11IMData->statusWindow)){722return;723}724725if (ON == False){726XUnmapWindow(dpy, statusWindow->w);727statusWindow->on = False;728return;729}730parent = JNU_CallMethodByName(GetJNIEnv(), NULL, pX11IMData->x11inputmethod,731"getCurrentParentWindow",732"()J").j;733if (statusWindow->parent != parent){734statusWindow->parent = parent;735}736XGetWindowAttributes(dpy, parent, &xwa);737XTranslateCoordinates(dpy,738parent, xwa.root,739xwa.x, xwa.y,740&x, &y,741&child);742if (statusWindow->x != x743|| statusWindow->y != y744|| statusWindow->height != xwa.height){745statusWindow->x = x;746statusWindow->y = y;747statusWindow->height = xwa.height;748x = statusWindow->x - statusWindow->off_x;749y = statusWindow->y + statusWindow->height - statusWindow->off_y;750if (x < 0 ){751x = 0;752}753if (x + statusWindow->statusW > statusWindow->rootW){754x = statusWindow->rootW - statusWindow->statusW;755}756if (y + statusWindow->statusH > statusWindow->rootH){757y = statusWindow->rootH - statusWindow->statusH;758}759XMoveWindow(dpy, statusWindow->w, x, y);760}761statusWindow->on = True;762XMapWindow(dpy, statusWindow->w);763}764765void paintStatusWindow(StatusWindow *statusWindow){766Window win = statusWindow->w;767GC lightgc = statusWindow->lightGC;768GC dimgc = statusWindow->dimGC;769GC bggc = statusWindow->bgGC;770GC fggc = statusWindow->fgGC;771772int width = statusWindow->statusW;773int height = statusWindow->statusH;774int bwidth = statusWindow->bWidth;775XFillRectangle(dpy, win, bggc, 0, 0, width, height);776/* draw border */777XDrawLine(dpy, win, fggc, 0, 0, width, 0);778XDrawLine(dpy, win, fggc, 0, height-1, width-1, height-1);779XDrawLine(dpy, win, fggc, 0, 0, 0, height-1);780XDrawLine(dpy, win, fggc, width-1, 0, width-1, height-1);781782XDrawLine(dpy, win, lightgc, 1, 1, width-bwidth, 1);783XDrawLine(dpy, win, lightgc, 1, 1, 1, height-2);784XDrawLine(dpy, win, lightgc, 1, height-2, width-bwidth, height-2);785XDrawLine(dpy, win, lightgc, width-bwidth-1, 1, width-bwidth-1, height-2);786787XDrawLine(dpy, win, dimgc, 2, 2, 2, height-3);788XDrawLine(dpy, win, dimgc, 2, height-3, width-bwidth-1, height-3);789XDrawLine(dpy, win, dimgc, 2, 2, width-bwidth-2, 2);790XDrawLine(dpy, win, dimgc, width-bwidth, 2, width-bwidth, height-3);791if (statusWindow->fontset){792XmbDrawString(dpy, win, statusWindow->fontset, fggc,793bwidth + 2, height - bwidth - 4,794statusWindow->status,795strlen(statusWindow->status));796}797else{798/*too bad we failed to create a fontset for this locale*/799XDrawString(dpy, win, fggc, bwidth + 2, height - bwidth - 4,800"[InputMethod ON]", strlen("[InputMethod ON]"));801}802}803804void statusWindowEventHandler(XEvent event){805JNIEnv *env = GetJNIEnv();806X11InputMethodData *pX11IMData = NULL;807StatusWindow *statusWindow;808809if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) {810currentX11InputMethodInstance = NULL;811return;812}813814if (NULL == currentX11InputMethodInstance815|| NULL == (pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance))816|| NULL == (statusWindow = pX11IMData->statusWindow)817|| statusWindow->w != event.xany.window){818return;819}820821switch (event.type){822case Expose:823paintStatusWindow(statusWindow);824break;825case MapNotify:826case ConfigureNotify:827{828/*need to reset the stackMode...*/829XWindowChanges xwc;830int value_make = CWStackMode;831xwc.stack_mode = TopIf;832XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);833}834break;835/*836case UnmapNotify:837case VisibilityNotify:838break;839*/840default:841break;842}843}844845static void adjustStatusWindow(Window shell){846JNIEnv *env = GetJNIEnv();847X11InputMethodData *pX11IMData = NULL;848StatusWindow *statusWindow;849850if (NULL == currentX11InputMethodInstance851|| !isX11InputMethodGRefInList(currentX11InputMethodInstance)852|| NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))853|| NULL == (statusWindow = pX11IMData->statusWindow)854|| !statusWindow->on) {855return;856}857{858XWindowAttributes xwa;859int x, y;860Window child;861XGetWindowAttributes(dpy, shell, &xwa);862XTranslateCoordinates(dpy,863shell, xwa.root,864xwa.x, xwa.y,865&x, &y,866&child);867if (statusWindow->x != x868|| statusWindow->y != y869|| statusWindow->height != xwa.height){870statusWindow->x = x;871statusWindow->y = y;872statusWindow->height = xwa.height;873874x = statusWindow->x - statusWindow->off_x;875y = statusWindow->y + statusWindow->height - statusWindow->off_y;876if (x < 0 ){877x = 0;878}879if (x + statusWindow->statusW > statusWindow->rootW){880x = statusWindow->rootW - statusWindow->statusW;881}882if (y + statusWindow->statusH > statusWindow->rootH){883y = statusWindow->rootH - statusWindow->statusH;884}885XMoveWindow(dpy, statusWindow->w, x, y);886}887}888}889#endif /* __linux__ || MACOSX */890/*891* Creates two XICs, one for active clients and the other for passive892* clients. All information on those XICs are stored in the893* X11InputMethodData given by the pX11IMData parameter.894*895* For active clients: Try to use preedit callback to support896* on-the-spot. If tc is not null, the XIC to be created will897* share the Status Area with Motif widgets (TextComponents). If the898* preferable styles can't be used, fallback to root-window styles. If899* root-window styles failed, fallback to None styles.900*901* For passive clients: Try to use root-window styles. If failed,902* fallback to None styles.903*/904static Bool905createXIC(JNIEnv * env, X11InputMethodData *pX11IMData, Window w)906{907XVaNestedList preedit = NULL;908XVaNestedList status = NULL;909XIMStyle on_the_spot_styles = XIMPreeditCallbacks,910active_styles = 0,911passive_styles = 0,912no_styles = 0;913XIMCallback *callbacks;914unsigned short i;915XIMStyles *im_styles;916char *ret = NULL;917918if (X11im == NULL) {919return False;920}921if (!w) {922return False;923}924925ret = XGetIMValues(X11im, XNQueryInputStyle, &im_styles, NULL);926927if (ret != NULL) {928jio_fprintf(stderr,"XGetIMValues: %s\n",ret);929return FALSE ;930}931932#if defined(__linux__) || defined(MACOSX)933on_the_spot_styles |= XIMStatusNothing;934935/*kinput does not support XIMPreeditCallbacks and XIMStatusArea936at the same time, so use StatusCallback to draw the status937ourself938*/939for (i = 0; i < im_styles->count_styles; i++) {940if (im_styles->supported_styles[i] == (XIMPreeditCallbacks | XIMStatusCallbacks)) {941on_the_spot_styles = (XIMPreeditCallbacks | XIMStatusCallbacks);942break;943}944}945#else /*! __linux__ && !MACOSX */946on_the_spot_styles |= XIMStatusNothing;947#endif /* __linux__ || MACOSX */948949for (i = 0; i < im_styles->count_styles; i++) {950active_styles |= im_styles->supported_styles[i] & on_the_spot_styles;951passive_styles |= im_styles->supported_styles[i] & ROOT_WINDOW_STYLES;952no_styles |= im_styles->supported_styles[i] & NO_STYLES;953}954955XFree(im_styles);956957if (active_styles != on_the_spot_styles) {958if (passive_styles == ROOT_WINDOW_STYLES)959active_styles = passive_styles;960else {961if (no_styles == NO_STYLES)962active_styles = passive_styles = NO_STYLES;963else964active_styles = passive_styles = 0;965}966} else {967if (passive_styles != ROOT_WINDOW_STYLES) {968if (no_styles == NO_STYLES)969active_styles = passive_styles = NO_STYLES;970else971active_styles = passive_styles = 0;972}973}974975if (active_styles == on_the_spot_styles) {976pX11IMData->ic_passive = XCreateIC(X11im,977XNClientWindow, w,978XNFocusWindow, w,979XNInputStyle, passive_styles,980NULL);981982callbacks = (XIMCallback *)malloc(sizeof(XIMCallback) * NCALLBACKS);983if (callbacks == (XIMCallback *)NULL)984return False;985pX11IMData->callbacks = callbacks;986987for (i = 0; i < NCALLBACKS; i++, callbacks++) {988callbacks->client_data = (XPointer) pX11IMData->x11inputmethod;989callbacks->callback = callback_funcs[i];990}991992callbacks = pX11IMData->callbacks;993preedit = (XVaNestedList)XVaCreateNestedList(0,994XNPreeditStartCallback, &callbacks[PreeditStartIndex],995XNPreeditDoneCallback, &callbacks[PreeditDoneIndex],996XNPreeditDrawCallback, &callbacks[PreeditDrawIndex],997XNPreeditCaretCallback, &callbacks[PreeditCaretIndex],998NULL);999if (preedit == (XVaNestedList)NULL)1000goto err;1001#if defined(__linux__) || defined(MACOSX)1002/*always try XIMStatusCallbacks for active client...*/1003{1004status = (XVaNestedList)XVaCreateNestedList(0,1005XNStatusStartCallback, &callbacks[StatusStartIndex],1006XNStatusDoneCallback, &callbacks[StatusDoneIndex],1007XNStatusDrawCallback, &callbacks[StatusDrawIndex],1008NULL);10091010if (status == NULL)1011goto err;1012pX11IMData->statusWindow = createStatusWindow(w);1013pX11IMData->ic_active = XCreateIC(X11im,1014XNClientWindow, w,1015XNFocusWindow, w,1016XNInputStyle, active_styles,1017XNPreeditAttributes, preedit,1018XNStatusAttributes, status,1019NULL);1020XFree((void *)status);1021XFree((void *)preedit);1022}1023#else /* !__linux__ && !MACOSX */1024pX11IMData->ic_active = XCreateIC(X11im,1025XNClientWindow, w,1026XNFocusWindow, w,1027XNInputStyle, active_styles,1028XNPreeditAttributes, preedit,1029NULL);1030XFree((void *)preedit);1031#endif /* __linux__ || MACOSX */1032} else {1033pX11IMData->ic_active = XCreateIC(X11im,1034XNClientWindow, w,1035XNFocusWindow, w,1036XNInputStyle, active_styles,1037NULL);1038pX11IMData->ic_passive = pX11IMData->ic_active;1039}10401041if (pX11IMData->ic_active == (XIC)01042|| pX11IMData->ic_passive == (XIC)0) {1043return False;1044}10451046/*1047* Use commit string call back if possible.1048* This will ensure the correct order of preedit text and commit text1049*/1050{1051XIMCallback cb;1052cb.client_data = (XPointer) pX11IMData->x11inputmethod;1053cb.callback = (XIMProc) CommitStringCallback;1054XSetICValues (pX11IMData->ic_active, XNCommitStringCallback, &cb, NULL);1055if (pX11IMData->ic_active != pX11IMData->ic_passive) {1056XSetICValues (pX11IMData->ic_passive, XNCommitStringCallback, &cb, NULL);1057}1058}10591060/* Add the global reference object to X11InputMethod to the list. */1061addToX11InputMethodGRefList(pX11IMData->x11inputmethod);10621063return True;10641065err:1066if (preedit)1067XFree((void *)preedit);1068THROW_OUT_OF_MEMORY_ERROR();1069return False;1070}10711072static void1073PreeditStartCallback(XIC ic, XPointer client_data, XPointer call_data)1074{1075/*ARGSUSED*/1076/* printf("Native: PreeditCaretCallback\n"); */1077}10781079static void1080PreeditDoneCallback(XIC ic, XPointer client_data, XPointer call_data)1081{1082/*ARGSUSED*/1083/* printf("Native: StatusStartCallback\n"); */1084}10851086/*1087* Translate the preedit draw callback items to Java values and invoke1088* X11InputMethod.dispatchComposedText().1089*1090* client_data: X11InputMethod object1091*/1092static void1093PreeditDrawCallback(XIC ic, XPointer client_data,1094XIMPreeditDrawCallbackStruct *pre_draw)1095{1096JNIEnv *env = GetJNIEnv();1097X11InputMethodData *pX11IMData = NULL;1098jmethodID x11imMethodID;10991100XIMText *text;1101jstring javastr = NULL;1102jintArray style = NULL;11031104/* printf("Native: PreeditDrawCallback() \n"); */1105if (pre_draw == NULL) {1106return;1107}1108AWT_LOCK();1109if (!isX11InputMethodGRefInList((jobject)client_data)) {1110if ((jobject)client_data == currentX11InputMethodInstance) {1111currentX11InputMethodInstance = NULL;1112}1113goto finally;1114}1115if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) {1116goto finally;1117}11181119if ((text = pre_draw->text) != NULL) {1120if (text->string.multi_byte != NULL) {1121if (pre_draw->text->encoding_is_wchar == False) {1122javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte);1123if (javastr == NULL) {1124goto finally;1125}1126} else {1127char *mbstr = wcstombsdmp(text->string.wide_char, text->length);1128if (mbstr == NULL) {1129goto finally;1130}1131javastr = JNU_NewStringPlatform(env, (const char *)mbstr);1132free(mbstr);1133if (javastr == NULL) {1134goto finally;1135}1136}1137}1138if (text->feedback != NULL) {1139int cnt;1140jint *tmpstyle;11411142style = (*env)->NewIntArray(env, text->length);1143if (JNU_IsNull(env, style)) {1144(*env)->ExceptionClear(env);1145THROW_OUT_OF_MEMORY_ERROR();1146goto finally;1147}11481149if (sizeof(XIMFeedback) == sizeof(jint)) {1150/*1151* Optimization to avoid copying the array1152*/1153(*env)->SetIntArrayRegion(env, style, 0,1154text->length, (jint *)text->feedback);1155} else {1156tmpstyle = (jint *)malloc(sizeof(jint)*(text->length));1157if (tmpstyle == (jint *) NULL) {1158THROW_OUT_OF_MEMORY_ERROR();1159goto finally;1160}1161for (cnt = 0; cnt < (int)text->length; cnt++)1162tmpstyle[cnt] = text->feedback[cnt];1163(*env)->SetIntArrayRegion(env, style, 0,1164text->length, (jint *)tmpstyle);1165}1166}1167}1168JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,1169"dispatchComposedText",1170"(Ljava/lang/String;[IIIIJ)V",1171javastr,1172style,1173(jint)pre_draw->chg_first,1174(jint)pre_draw->chg_length,1175(jint)pre_draw->caret,1176awt_util_nowMillisUTC());1177finally:1178AWT_UNLOCK();1179return;1180}11811182static void1183PreeditCaretCallback(XIC ic, XPointer client_data,1184XIMPreeditCaretCallbackStruct *pre_caret)1185{1186/*ARGSUSED*/1187/* printf("Native: PreeditCaretCallback\n"); */11881189}11901191#if defined(__linux__) || defined(MACOSX)1192static void1193StatusStartCallback(XIC ic, XPointer client_data, XPointer call_data)1194{1195/*ARGSUSED*/1196/*printf("StatusStartCallback:\n"); */11971198}11991200static void1201StatusDoneCallback(XIC ic, XPointer client_data, XPointer call_data)1202{1203/*ARGSUSED*/1204/*printf("StatusDoneCallback:\n"); */12051206}12071208static void1209StatusDrawCallback(XIC ic, XPointer client_data,1210XIMStatusDrawCallbackStruct *status_draw)1211{1212/*ARGSUSED*/1213/*printf("StatusDrawCallback:\n"); */1214JNIEnv *env = GetJNIEnv();1215X11InputMethodData *pX11IMData = NULL;1216StatusWindow *statusWindow;12171218AWT_LOCK();12191220if (!isX11InputMethodGRefInList((jobject)client_data)) {1221if ((jobject)client_data == currentX11InputMethodInstance) {1222currentX11InputMethodInstance = NULL;1223}1224goto finally;1225}12261227if (NULL == (pX11IMData = getX11InputMethodData(env, (jobject)client_data))1228|| NULL == (statusWindow = pX11IMData->statusWindow)){1229goto finally;1230}1231currentX11InputMethodInstance = (jobject)client_data;12321233if (status_draw->type == XIMTextType){1234XIMText *text = (status_draw->data).text;1235if (text != NULL){1236if (text->string.multi_byte != NULL){1237strcpy(statusWindow->status, text->string.multi_byte);1238}1239else{1240char *mbstr = wcstombsdmp(text->string.wide_char, text->length);1241strcpy(statusWindow->status, mbstr);1242}1243statusWindow->on = True;1244onoffStatusWindow(pX11IMData, statusWindow->parent, True);1245paintStatusWindow(statusWindow);1246}1247else {1248statusWindow->on = False;1249/*just turnoff the status window1250paintStatusWindow(statusWindow);1251*/1252onoffStatusWindow(pX11IMData, 0, False);1253}1254}12551256finally:1257AWT_UNLOCK();1258}1259#endif /* __linux__ || MACOSX */12601261static void CommitStringCallback(XIC ic, XPointer client_data, XPointer call_data) {1262JNIEnv *env = GetJNIEnv();1263XIMText * text = (XIMText *)call_data;1264X11InputMethodData *pX11IMData = NULL;1265jstring javastr;12661267AWT_LOCK();12681269if (!isX11InputMethodGRefInList((jobject)client_data)) {1270if ((jobject)client_data == currentX11InputMethodInstance) {1271currentX11InputMethodInstance = NULL;1272}1273goto finally;1274}12751276if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) {1277goto finally;1278}1279currentX11InputMethodInstance = (jobject)client_data;12801281if (text->encoding_is_wchar == False) {1282javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte);1283} else {1284char *mbstr = wcstombsdmp(text->string.wide_char, text->length);1285if (mbstr == NULL) {1286goto finally;1287}1288javastr = JNU_NewStringPlatform(env, (const char *)mbstr);1289free(mbstr);1290}12911292if (javastr != NULL) {1293JNU_CallMethodByName(env, NULL,1294pX11IMData->x11inputmethod,1295"dispatchCommittedText",1296"(Ljava/lang/String;J)V",1297javastr,1298awt_util_nowMillisUTC());1299}1300finally:1301AWT_UNLOCK();1302}13031304static void OpenXIMCallback(Display *display, XPointer client_data, XPointer call_data) {1305XIMCallback ximCallback;13061307X11im = XOpenIM(display, NULL, NULL, NULL);1308if (X11im == NULL) {1309return;1310}13111312ximCallback.callback = (XIMProc)DestroyXIMCallback;1313ximCallback.client_data = NULL;1314XSetIMValues(X11im, XNDestroyCallback, &ximCallback, NULL);1315}13161317static void DestroyXIMCallback(XIM im, XPointer client_data, XPointer call_data) {1318/* mark that XIM server was destroyed */1319X11im = NULL;1320JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);13211322AWT_LOCK();1323/* free the old pX11IMData and set it to null. this also avoids crashing1324* the jvm if the XIM server reappears */1325while (x11InputMethodGRefListHead != NULL) {1326getX11InputMethodData(env, x11InputMethodGRefListHead->inputMethodGRef);1327}1328AWT_UNLOCK();1329}13301331/*1332* Class: sun_awt_X11InputMethod1333* Method: initIDs1334* Signature: ()V1335*/13361337/* This function gets called from the static initializer for1338X11InputMethod.java1339to initialize the fieldIDs for fields that may be accessed from C */1340JNIEXPORT void JNICALL1341Java_sun_awt_X11InputMethod_initIDs(JNIEnv *env, jclass cls)1342{1343x11InputMethodIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J");1344}134513461347JNIEXPORT jboolean JNICALL1348Java_sun_awt_X11_XInputMethod_openXIMNative(JNIEnv *env,1349jobject this,1350jlong display)1351{1352Bool registered;13531354AWT_LOCK();13551356dpy = (Display *)jlong_to_ptr(display);13571358/* Use IMInstantiate call back only on Linux, as there is a bug in Solaris1359(4768335)1360*/1361#if defined(__linux__) || defined(MACOSX)1362registered = XRegisterIMInstantiateCallback(dpy, NULL, NULL,1363NULL, (XIDProc)OpenXIMCallback, NULL);1364if (!registered) {1365/* directly call openXIM callback */1366#endif1367OpenXIMCallback(dpy, NULL, NULL);1368#if defined(__linux__) || defined(MACOSX)1369}1370#endif13711372AWT_UNLOCK();13731374return JNI_TRUE;1375}13761377JNIEXPORT jboolean JNICALL1378Java_sun_awt_X11_XInputMethod_createXICNative(JNIEnv *env,1379jobject this,1380jlong window)1381{1382X11InputMethodData *pX11IMData;1383jobject globalRef;1384XIC ic;13851386AWT_LOCK();13871388if (!window) {1389JNU_ThrowNullPointerException(env, "NullPointerException");1390AWT_UNLOCK();1391return JNI_FALSE;1392}13931394pX11IMData = (X11InputMethodData *) calloc(1, sizeof(X11InputMethodData));1395if (pX11IMData == NULL) {1396THROW_OUT_OF_MEMORY_ERROR();1397AWT_UNLOCK();1398return JNI_FALSE;1399}14001401globalRef = (*env)->NewGlobalRef(env, this);1402pX11IMData->x11inputmethod = globalRef;1403#if defined(__linux__) || defined(MACOSX)1404pX11IMData->statusWindow = NULL;1405#endif /* __linux__ || MACOSX */14061407pX11IMData->lookup_buf = 0;1408pX11IMData->lookup_buf_len = 0;14091410if (createXIC(env, pX11IMData, (Window)window) == False) {1411destroyX11InputMethodData((JNIEnv *) NULL, pX11IMData);1412pX11IMData = (X11InputMethodData *) NULL;1413if ((*env)->ExceptionCheck(env)) {1414goto finally;1415}1416}14171418setX11InputMethodData(env, this, pX11IMData);14191420finally:1421AWT_UNLOCK();1422return (pX11IMData != NULL);1423}14241425JNIEXPORT void JNICALL1426Java_sun_awt_X11_XInputMethod_setXICFocusNative(JNIEnv *env,1427jobject this,1428jlong w,1429jboolean req,1430jboolean active)1431{1432X11InputMethodData *pX11IMData;1433AWT_LOCK();1434pX11IMData = getX11InputMethodData(env, this);1435if (pX11IMData == NULL) {1436AWT_UNLOCK();1437return;1438}14391440if (req) {1441if (!w) {1442AWT_UNLOCK();1443return;1444}1445pX11IMData->current_ic = active ?1446pX11IMData->ic_active : pX11IMData->ic_passive;1447/*1448* On Solaris2.6, setXICWindowFocus() has to be invoked1449* before setting focus.1450*/1451setXICWindowFocus(pX11IMData->current_ic, w);1452setXICFocus(pX11IMData->current_ic, req);1453currentX11InputMethodInstance = pX11IMData->x11inputmethod;1454currentFocusWindow = w;1455#if defined(__linux__) || defined(MACOSX)1456if (active && pX11IMData->statusWindow && pX11IMData->statusWindow->on)1457onoffStatusWindow(pX11IMData, w, True);1458#endif1459} else {1460currentX11InputMethodInstance = NULL;1461currentFocusWindow = 0;1462#if defined(__linux__) || defined(MACOSX)1463onoffStatusWindow(pX11IMData, 0, False);1464if (pX11IMData->current_ic != NULL)1465#endif1466setXICFocus(pX11IMData->current_ic, req);14671468pX11IMData->current_ic = (XIC)0;1469}14701471XFlush(dpy);1472AWT_UNLOCK();1473}14741475JNIEXPORT void JNICALL1476Java_sun_awt_X11InputMethod_turnoffStatusWindow(JNIEnv *env,1477jobject this)1478{1479#if defined(__linux__) || defined(MACOSX)1480X11InputMethodData *pX11IMData;1481StatusWindow *statusWindow;14821483AWT_LOCK();14841485if (NULL == currentX11InputMethodInstance1486|| !isX11InputMethodGRefInList(currentX11InputMethodInstance)1487|| NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))1488|| NULL == (statusWindow = pX11IMData->statusWindow)1489|| !statusWindow->on ){1490AWT_UNLOCK();1491return;1492}1493onoffStatusWindow(pX11IMData, 0, False);14941495AWT_UNLOCK();1496#endif1497}14981499JNIEXPORT void JNICALL1500Java_sun_awt_X11InputMethod_disposeXIC(JNIEnv *env,1501jobject this)1502{1503X11InputMethodData *pX11IMData = NULL;15041505AWT_LOCK();1506pX11IMData = getX11InputMethodData(env, this);1507if (pX11IMData == NULL) {1508AWT_UNLOCK();1509return;1510}15111512setX11InputMethodData(env, this, NULL);15131514if (pX11IMData->x11inputmethod == currentX11InputMethodInstance) {1515currentX11InputMethodInstance = NULL;1516currentFocusWindow = 0;1517}1518destroyX11InputMethodData(env, pX11IMData);1519AWT_UNLOCK();1520}15211522JNIEXPORT jstring JNICALL1523Java_sun_awt_X11InputMethod_resetXIC(JNIEnv *env,1524jobject this)1525{1526X11InputMethodData *pX11IMData;1527char *xText = NULL;1528jstring jText = (jstring)0;15291530AWT_LOCK();1531pX11IMData = getX11InputMethodData(env, this);1532if (pX11IMData == NULL) {1533AWT_UNLOCK();1534return jText;1535}15361537if (pX11IMData->current_ic)1538xText = XmbResetIC(pX11IMData->current_ic);1539else {1540/*1541* If there is no reference to the current XIC, try to reset both XICs.1542*/1543xText = XmbResetIC(pX11IMData->ic_active);1544/*it may also means that the real client component does1545not have focus -- has been deactivated... its xic should1546not have the focus, bug#4284651 showes reset XIC for htt1547may bring the focus back, so de-focus it again.1548*/1549setXICFocus(pX11IMData->ic_active, FALSE);1550if (pX11IMData->ic_active != pX11IMData->ic_passive) {1551char *tmpText = XmbResetIC(pX11IMData->ic_passive);1552setXICFocus(pX11IMData->ic_passive, FALSE);1553if (xText == (char *)NULL && tmpText)1554xText = tmpText;1555}15561557}1558if (xText != NULL) {1559jText = JNU_NewStringPlatform(env, (const char *)xText);1560XFree((void *)xText);1561}15621563AWT_UNLOCK();1564return jText;1565}15661567/*1568* Class: sun_awt_X11InputMethod1569* Method: setCompositionEnabledNative1570* Signature: (ZJ)V1571*1572* This method tries to set the XNPreeditState attribute associated with the current1573* XIC to the passed in 'enable' state.1574*1575* Return JNI_TRUE if XNPreeditState attribute is successfully changed to the1576* 'enable' state; Otherwise, if XSetICValues fails to set this attribute,1577* java.lang.UnsupportedOperationException will be thrown. JNI_FALSE is returned if this1578* method fails due to other reasons.1579*1580*/1581JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethod_setCompositionEnabledNative1582(JNIEnv *env, jobject this, jboolean enable)1583{1584X11InputMethodData *pX11IMData;1585char * ret = NULL;15861587AWT_LOCK();1588pX11IMData = getX11InputMethodData(env, this);15891590if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) {1591AWT_UNLOCK();1592return JNI_FALSE;1593}15941595ret = XSetICValues(pX11IMData->current_ic, XNPreeditState,1596(enable ? XIMPreeditEnable : XIMPreeditDisable), NULL);1597AWT_UNLOCK();15981599if ((ret != 0) && (strcmp(ret, XNPreeditState) == 0)) {1600JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");1601}16021603return (jboolean)(ret == 0);1604}16051606/*1607* Class: sun_awt_X11InputMethod1608* Method: isCompositionEnabledNative1609* Signature: (J)Z1610*1611* This method tries to get the XNPreeditState attribute associated with the current XIC.1612*1613* Return JNI_TRUE if the XNPreeditState is successfully retrieved. Otherwise, if1614* XGetICValues fails to get this attribute, java.lang.UnsupportedOperationException1615* will be thrown. JNI_FALSE is returned if this method fails due to other reasons.1616*1617*/1618JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethod_isCompositionEnabledNative1619(JNIEnv *env, jobject this)1620{1621X11InputMethodData *pX11IMData = NULL;1622char * ret = NULL;1623XIMPreeditState state;16241625AWT_LOCK();1626pX11IMData = getX11InputMethodData(env, this);16271628if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) {1629AWT_UNLOCK();1630return JNI_FALSE;1631}16321633ret = XGetICValues(pX11IMData->current_ic, XNPreeditState, &state, NULL);1634AWT_UNLOCK();16351636if ((ret != 0) && (strcmp(ret, XNPreeditState) == 0)) {1637JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");1638return JNI_FALSE;1639}16401641return (jboolean)(state == XIMPreeditEnable);1642}16431644JNIEXPORT void JNICALL Java_sun_awt_X11_XInputMethod_adjustStatusWindow1645(JNIEnv *env, jobject this, jlong window)1646{1647#if defined(__linux__) || defined(MACOSX)1648AWT_LOCK();1649adjustStatusWindow(window);1650AWT_UNLOCK();1651#endif1652}165316541655