Path: blob/master/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c
41155 views
/*1* Copyright (c) 1997, 2021, 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 "awt.h"30#include "awt_p.h"3132#include <sun_awt_X11InputMethodBase.h>33#include <sun_awt_X11_XInputMethod.h>3435#include <stdio.h>36#include <stdlib.h>37#include <sys/time.h>38#include <X11/keysym.h>39#include <X11/Xlib.h>4041#define THROW_OUT_OF_MEMORY_ERROR() \42JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL)4344struct X11InputMethodIDs {45jfieldID pData;46} x11InputMethodIDs;4748static int PreeditStartCallback(XIC, XPointer, XPointer);49static void PreeditDoneCallback(XIC, XPointer, XPointer);50static void PreeditDrawCallback(XIC, XPointer,51XIMPreeditDrawCallbackStruct *);52static void PreeditCaretCallback(XIC, XPointer,53XIMPreeditCaretCallbackStruct *);54#if defined(__linux__)55static void StatusStartCallback(XIC, XPointer, XPointer);56static void StatusDoneCallback(XIC, XPointer, XPointer);57static void StatusDrawCallback(XIC, XPointer,58XIMStatusDrawCallbackStruct *);59#endif6061#define ROOT_WINDOW_STYLES (XIMPreeditNothing | XIMStatusNothing)62#define NO_STYLES (XIMPreeditNone | XIMStatusNone)6364#define PreeditStartIndex 065#define PreeditDoneIndex 166#define PreeditDrawIndex 267#define PreeditCaretIndex 368#if defined(__linux__)69#define StatusStartIndex 470#define StatusDoneIndex 571#define StatusDrawIndex 672#define NCALLBACKS 773#else74#define NCALLBACKS 475#endif7677/*78* Callback function pointers: the order has to match the *Index79* values above.80*/81static XIMProc callback_funcs[NCALLBACKS] = {82(XIMProc)(void *)&PreeditStartCallback,83(XIMProc)PreeditDoneCallback,84(XIMProc)PreeditDrawCallback,85(XIMProc)PreeditCaretCallback,86#if defined(__linux__)87(XIMProc)StatusStartCallback,88(XIMProc)StatusDoneCallback,89(XIMProc)StatusDrawCallback,90#endif91};9293#if defined(__linux__)94#define MAX_STATUS_LEN 10095typedef struct {96Window w; /*status window id */97Window root; /*the root window id */98Window parent; /*parent shell window */99int x, y; /*parent's upperleft position */100int width, height; /*parent's width, height */101GC lightGC; /*gc for light border */102GC dimGC; /*gc for dim border */103GC bgGC; /*normal painting */104GC fgGC; /*normal painting */105int statusW, statusH; /*status window's w, h */106int rootW, rootH; /*root window's w, h */107int bWidth; /*border width */108char status[MAX_STATUS_LEN]; /*status text */109XFontSet fontset; /*fontset for drawing */110int off_x, off_y;111Bool on; /*if the status window on*/112} StatusWindow;113#endif114115/*116* X11InputMethodData keeps per X11InputMethod instance information. A pointer117* to this data structure is kept in an X11InputMethod object (pData).118*/119typedef struct _X11InputMethodData {120XIC current_ic; /* current X Input Context */121XIC ic_active; /* X Input Context for active clients */122XIC ic_passive; /* X Input Context for passive clients */123XIMCallback *callbacks; /* callback parameters */124jobject x11inputmethod; /* global ref to X11InputMethod instance */125/* associated with the XIC */126#if defined(__linux__)127StatusWindow *statusWindow; /* our own status window */128#endif129char *lookup_buf; /* buffer used for XmbLookupString */130int lookup_buf_len; /* lookup buffer size in bytes */131} X11InputMethodData;132133/*134* When XIC is created, a global reference is created for135* sun.awt.X11InputMethod object so that it could be used by the XIM callback136* functions. This could be a dangerous thing to do when the original137* X11InputMethod object is garbage collected and as a result,138* destroyX11InputMethodData is called to delete the global reference.139* If any XIM callback function still holds and uses the "already deleted"140* global reference, disaster is going to happen. So we have to maintain141* a list for these global references which is consulted first when the142* callback functions or any function tries to use "currentX11InputMethodObject"143* which always refers to the global reference try to use it.144*145*/146typedef struct _X11InputMethodGRefNode {147jobject inputMethodGRef;148struct _X11InputMethodGRefNode* next;149} X11InputMethodGRefNode;150151X11InputMethodGRefNode *x11InputMethodGRefListHead = NULL;152153/* reference to the current X11InputMethod instance, it is always154point to the global reference to the X11InputMethodObject since155it could be referenced by different threads. */156jobject currentX11InputMethodInstance = NULL;157158Window currentFocusWindow = 0; /* current window that has focus for input159method. (the best place to put this160information should be161currentX11InputMethodInstance's pData) */162static XIM X11im = NULL;163Display * dpy = NULL;164165#define GetJNIEnv() (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2)166167static void DestroyXIMCallback(XIM, XPointer, XPointer);168static void OpenXIMCallback(Display *, XPointer, XPointer);169/* Solaris XIM Extention */170#define XNCommitStringCallback "commitStringCallback"171static void CommitStringCallback(XIC, XPointer, XPointer);172173static X11InputMethodData * getX11InputMethodData(JNIEnv *, jobject);174static void setX11InputMethodData(JNIEnv *, jobject, X11InputMethodData *);175static void destroyX11InputMethodData(JNIEnv *, X11InputMethodData *);176static void freeX11InputMethodData(JNIEnv *, X11InputMethodData *);177#if defined(__linux__)178static Window getParentWindow(Window);179#endif180181/*182* This function is stolen from /src/solaris/hpi/src/system_md.c183* It is used in setting the time in Java-level InputEvents184*/185jlong186awt_util_nowMillisUTC()187{188struct timeval t;189gettimeofday(&t, NULL);190return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000);191}192193/*194* Converts the wchar_t string to a multi-byte string calling wcstombs(). A195* buffer is allocated by malloc() to store the multi-byte string. NULL is196* returned if the given wchar_t string pointer is NULL or buffer allocation is197* failed.198*/199static char *200wcstombsdmp(wchar_t *wcs, int len)201{202size_t n;203char *mbs;204205if (wcs == NULL)206return NULL;207208n = len*MB_CUR_MAX + 1;209210mbs = (char *) malloc(n * sizeof(char));211if (mbs == NULL) {212THROW_OUT_OF_MEMORY_ERROR();213return NULL;214}215216/* TODO: check return values... Handle invalid characters properly... */217if (wcstombs(mbs, wcs, n) == (size_t)-1) {218free(mbs);219return NULL;220}221222return mbs;223}224225/*226* Returns True if the global reference is still in the list,227* otherwise False.228*/229static Bool isX11InputMethodGRefInList(jobject imGRef) {230X11InputMethodGRefNode *pX11InputMethodGRef = x11InputMethodGRefListHead;231232if (imGRef == NULL) {233return False;234}235236while (pX11InputMethodGRef != NULL) {237if (pX11InputMethodGRef->inputMethodGRef == imGRef) {238return True;239}240pX11InputMethodGRef = pX11InputMethodGRef->next;241}242243return False;244}245246/*247* Add the new created global reference to the list.248*/249static void addToX11InputMethodGRefList(jobject newX11InputMethodGRef) {250X11InputMethodGRefNode *newNode = NULL;251252if (newX11InputMethodGRef == NULL ||253isX11InputMethodGRefInList(newX11InputMethodGRef)) {254return;255}256257newNode = (X11InputMethodGRefNode *)malloc(sizeof(X11InputMethodGRefNode));258259if (newNode == NULL) {260return;261} else {262newNode->inputMethodGRef = newX11InputMethodGRef;263newNode->next = x11InputMethodGRefListHead;264x11InputMethodGRefListHead = newNode;265}266}267268/*269* Remove the global reference from the list.270*/271static void removeX11InputMethodGRefFromList(jobject x11InputMethodGRef) {272X11InputMethodGRefNode *pX11InputMethodGRef = NULL;273X11InputMethodGRefNode *cX11InputMethodGRef = x11InputMethodGRefListHead;274275if (x11InputMethodGRefListHead == NULL ||276x11InputMethodGRef == NULL) {277return;278}279280/* cX11InputMethodGRef always refers to the current node while281pX11InputMethodGRef refers to the previous node.282*/283while (cX11InputMethodGRef != NULL) {284if (cX11InputMethodGRef->inputMethodGRef == x11InputMethodGRef) {285break;286}287pX11InputMethodGRef = cX11InputMethodGRef;288cX11InputMethodGRef = cX11InputMethodGRef->next;289}290291if (cX11InputMethodGRef == NULL) {292return; /* Not found. */293}294295if (cX11InputMethodGRef == x11InputMethodGRefListHead) {296x11InputMethodGRefListHead = x11InputMethodGRefListHead->next;297} else {298pX11InputMethodGRef->next = cX11InputMethodGRef->next;299}300free(cX11InputMethodGRef);301302return;303}304305306static X11InputMethodData * getX11InputMethodData(JNIEnv * env, jobject imInstance) {307X11InputMethodData *pX11IMData =308(X11InputMethodData *)JNU_GetLongFieldAsPtr(env, imInstance, x11InputMethodIDs.pData);309310/*311* In case the XIM server was killed somehow, reset X11InputMethodData.312*/313if (X11im == NULL && pX11IMData != NULL) {314JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,315"flushText",316"()V");317JNU_CHECK_EXCEPTION_RETURN(env, NULL);318/* IMPORTANT:319The order of the following calls is critical since "imInstance" may320point to the global reference itself, if "freeX11InputMethodData" is called321first, the global reference will be destroyed and "setX11InputMethodData"322will in fact fail silently. So pX11IMData will not be set to NULL.323This could make the original java object refers to a deleted pX11IMData324object.325*/326setX11InputMethodData(env, imInstance, NULL);327freeX11InputMethodData(env, pX11IMData);328pX11IMData = NULL;329}330331return pX11IMData;332}333334static void setX11InputMethodData(JNIEnv * env, jobject imInstance, X11InputMethodData *pX11IMData) {335JNU_SetLongFieldFromPtr(env, imInstance, x11InputMethodIDs.pData, pX11IMData);336}337338/* this function should be called within AWT_LOCK() */339static void340destroyX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData)341{342/*343* Destroy XICs344*/345if (pX11IMData == NULL) {346return;347}348349if (pX11IMData->ic_active != (XIC)0) {350XUnsetICFocus(pX11IMData->ic_active);351XDestroyIC(pX11IMData->ic_active);352if (pX11IMData->ic_active != pX11IMData->ic_passive) {353if (pX11IMData->ic_passive != (XIC)0) {354XUnsetICFocus(pX11IMData->ic_passive);355XDestroyIC(pX11IMData->ic_passive);356}357pX11IMData->ic_passive = (XIC)0;358pX11IMData->current_ic = (XIC)0;359}360}361362freeX11InputMethodData(env, pX11IMData);363}364365static void366freeX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData)367{368#if defined(__linux__)369if (pX11IMData->statusWindow != NULL){370StatusWindow *sw = pX11IMData->statusWindow;371XFreeGC(awt_display, sw->lightGC);372XFreeGC(awt_display, sw->dimGC);373XFreeGC(awt_display, sw->bgGC);374XFreeGC(awt_display, sw->fgGC);375if (sw->fontset != NULL) {376XFreeFontSet(awt_display, sw->fontset);377}378XDestroyWindow(awt_display, sw->w);379free((void*)sw);380}381#endif382383if (pX11IMData->callbacks)384free((void *)pX11IMData->callbacks);385386if (env) {387/* Remove the global reference from the list, so that388the callback function or whoever refers to it could know.389*/390removeX11InputMethodGRefFromList(pX11IMData->x11inputmethod);391(*env)->DeleteGlobalRef(env, pX11IMData->x11inputmethod);392}393394if (pX11IMData->lookup_buf) {395free((void *)pX11IMData->lookup_buf);396}397398free((void *)pX11IMData);399}400401/*402* Sets or unsets the focus to the given XIC.403*/404static void405setXICFocus(XIC ic, unsigned short req)406{407if (ic == NULL) {408(void)fprintf(stderr, "Couldn't find X Input Context\n");409return;410}411if (req == 1)412XSetICFocus(ic);413else414XUnsetICFocus(ic);415}416417/*418* Sets the focus window to the given XIC.419*/420static void421setXICWindowFocus(XIC ic, Window w)422{423if (ic == NULL) {424(void)fprintf(stderr, "Couldn't find X Input Context\n");425return;426}427(void) XSetICValues(ic, XNFocusWindow, w, NULL);428}429430/*431* Invokes XmbLookupString() to get something from the XIM. It invokes432* X11InputMethod.dispatchCommittedText() if XmbLookupString() returns433* committed text. This function is called from handleKeyEvent in canvas.c and434* it's under the Motif event loop thread context.435*436* Buffer usage: There is a bug in XFree86-4.3.0 XmbLookupString implementation,437* where it never returns XBufferOverflow. We need to allocate the initial lookup buffer438* big enough, so that the possibility that user encounters this problem is relatively439* small. When this bug gets fixed, we can make the initial buffer size smaller.440* Note that XmbLookupString() sometimes produces a non-null-terminated string.441*442* Returns True when there is a keysym value to be handled.443*/444#define INITIAL_LOOKUP_BUF_SIZE 512445446Boolean447awt_x11inputmethod_lookupString(XKeyPressedEvent *event, KeySym *keysymp)448{449JNIEnv *env = GetJNIEnv();450X11InputMethodData *pX11IMData = NULL;451KeySym keysym = NoSymbol;452Status status;453int mblen;454jstring javastr;455XIC ic;456Boolean result = True;457static Boolean composing = False;458459/*460printf("lookupString: entering...\n");461*/462463if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) {464currentX11InputMethodInstance = NULL;465return False;466}467468pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance);469470if (pX11IMData == NULL) {471#if defined(__linux__)472return False;473#else474return result;475#endif476}477478if ((ic = pX11IMData->current_ic) == (XIC)0){479#if defined(__linux__)480return False;481#else482return result;483#endif484}485486/* allocate the lookup buffer at the first invocation */487if (pX11IMData->lookup_buf_len == 0) {488pX11IMData->lookup_buf = (char *)malloc(INITIAL_LOOKUP_BUF_SIZE);489if (pX11IMData->lookup_buf == NULL) {490THROW_OUT_OF_MEMORY_ERROR();491return result;492}493pX11IMData->lookup_buf_len = INITIAL_LOOKUP_BUF_SIZE;494}495496mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf,497pX11IMData->lookup_buf_len - 1, &keysym, &status);498499/*500* In case of overflow, a buffer is allocated and it retries501* XmbLookupString().502*/503if (status == XBufferOverflow) {504free((void *)pX11IMData->lookup_buf);505pX11IMData->lookup_buf_len = 0;506pX11IMData->lookup_buf = (char *)malloc(mblen + 1);507if (pX11IMData->lookup_buf == NULL) {508THROW_OUT_OF_MEMORY_ERROR();509return result;510}511pX11IMData->lookup_buf_len = mblen + 1;512mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf,513pX11IMData->lookup_buf_len - 1, &keysym, &status);514}515pX11IMData->lookup_buf[mblen] = 0;516517/* Get keysym without taking modifiers into account first to map518* to AWT keyCode table.519*/520switch (status) {521case XLookupBoth:522if (!composing) {523if (event->keycode != 0) {524*keysymp = keysym;525result = False;526break;527}528}529composing = False;530/*FALLTHRU*/531case XLookupChars:532/*533printf("lookupString: status=XLookupChars, type=%d, state=%x, keycode=%x, keysym=%x\n",534event->type, event->state, event->keycode, keysym);535*/536javastr = JNU_NewStringPlatform(env, (const char *)pX11IMData->lookup_buf);537if (javastr != NULL) {538JNU_CallMethodByName(env, NULL,539currentX11InputMethodInstance,540"dispatchCommittedText",541"(Ljava/lang/String;J)V",542javastr,543event->time);544}545break;546547case XLookupKeySym:548/*549printf("lookupString: status=XLookupKeySym, type=%d, state=%x, keycode=%x, keysym=%x\n",550event->type, event->state, event->keycode, keysym);551*/552if (keysym == XK_Multi_key)553composing = True;554if (! composing) {555*keysymp = keysym;556result = False;557}558break;559560case XLookupNone:561/*562printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n",563event->type, event->state, event->keycode, keysym);564*/565break;566}567568return result;569}570571#if defined(__linux__)572static StatusWindow *createStatusWindow(Window parent) {573StatusWindow *statusWindow;574XSetWindowAttributes attrib;575unsigned long attribmask;576Window containerWindow;577Window status;578Window child;579XWindowAttributes xwa;580XWindowAttributes xxwa;581/* Variable for XCreateFontSet()*/582char **mclr;583int mccr = 0;584char *dsr;585unsigned long bg, fg, light, dim;586int x, y, off_x, off_y, xx, yy;587unsigned int w, h, bw, depth;588XGCValues values;589unsigned long valuemask = 0; /*ignore XGCvalue and use defaults*/590int screen = 0;591int i;592AwtGraphicsConfigDataPtr adata;593extern int awt_numScreens;594/*hardcode the size right now, should get the size base on font*/595int width=80, height=22;596Window rootWindow;597Window *ignoreWindowPtr;598unsigned int ignoreUnit;599600XGetGeometry(dpy, parent, &rootWindow, &x, &y, &w, &h, &bw, &depth);601602attrib.override_redirect = True;603attribmask = CWOverrideRedirect;604for (i = 0; i < awt_numScreens; i++) {605if (RootWindow(dpy, i) == rootWindow) {606screen = i;607break;608}609}610adata = getDefaultConfig(screen);611bg = adata->AwtColorMatch(255, 255, 255, adata);612fg = adata->AwtColorMatch(0, 0, 0, adata);613light = adata->AwtColorMatch(195, 195, 195, adata);614dim = adata->AwtColorMatch(128, 128, 128, adata);615616XGetWindowAttributes(dpy, parent, &xwa);617bw = 2; /*xwa.border_width does not have the correct value*/618619/*compare the size difference between parent container620and shell widget, the diff should be the border frame621and title bar height (?)*/622623XQueryTree( dpy,624parent,625&rootWindow,626&containerWindow,627&ignoreWindowPtr,628&ignoreUnit);629XGetWindowAttributes(dpy, containerWindow, &xxwa);630631off_x = (xxwa.width - xwa.width) / 2;632off_y = xxwa.height - xwa.height - off_x; /*it's magic:-) */633634/*get the size of root window*/635XGetWindowAttributes(dpy, rootWindow, &xxwa);636637XTranslateCoordinates(dpy,638parent, xwa.root,639xwa.x, xwa.y,640&x, &y,641&child);642xx = x - off_x;643yy = y + xwa.height - off_y;644if (xx < 0 ){645xx = 0;646}647if (xx + width > xxwa.width) {648xx = xxwa.width - width;649}650if (yy + height > xxwa.height) {651yy = xxwa.height - height;652}653654status = XCreateWindow(dpy,655xwa.root,656xx, yy,657width, height,6580,659xwa.depth,660InputOutput,661adata->awt_visInfo.visual,662attribmask, &attrib);663XSelectInput(dpy, status,664ExposureMask | StructureNotifyMask | EnterWindowMask |665LeaveWindowMask | VisibilityChangeMask);666statusWindow = (StatusWindow*) calloc(1, sizeof(StatusWindow));667if (statusWindow == NULL){668THROW_OUT_OF_MEMORY_ERROR();669return NULL;670}671statusWindow->w = status;672//12, 13-point fonts673statusWindow->fontset = XCreateFontSet(dpy,674"-*-*-medium-r-normal-*-*-120-*-*-*-*," \675"-*-*-medium-r-normal-*-*-130-*-*-*-*",676&mclr, &mccr, &dsr);677/* In case we didn't find the font set, release the list of missing characters */678if (mccr > 0) {679XFreeStringList(mclr);680}681statusWindow->parent = parent;682statusWindow->on = False;683statusWindow->x = x;684statusWindow->y = y;685statusWindow->width = xwa.width;686statusWindow->height = xwa.height;687statusWindow->off_x = off_x;688statusWindow->off_y = off_y;689statusWindow->bWidth = bw;690statusWindow->statusH = height;691statusWindow->statusW = width;692statusWindow->rootH = xxwa.height;693statusWindow->rootW = xxwa.width;694statusWindow->lightGC = XCreateGC(dpy, status, valuemask, &values);695XSetForeground(dpy, statusWindow->lightGC, light);696statusWindow->dimGC = XCreateGC(dpy, status, valuemask, &values);697XSetForeground(dpy, statusWindow->dimGC, dim);698statusWindow->fgGC = XCreateGC(dpy, status, valuemask, &values);699XSetForeground(dpy, statusWindow->fgGC, fg);700statusWindow->bgGC = XCreateGC(dpy, status, valuemask, &values);701XSetForeground(dpy, statusWindow->bgGC, bg);702return statusWindow;703}704705/* This method is to turn off or turn on the status window. */706static void onoffStatusWindow(X11InputMethodData* pX11IMData,707Window parent,708Bool ON){709XWindowAttributes xwa;710Window child;711int x, y;712StatusWindow *statusWindow = NULL;713714if (NULL == currentX11InputMethodInstance ||715NULL == pX11IMData ||716NULL == (statusWindow = pX11IMData->statusWindow)){717return;718}719720if (ON == False) {721XUnmapWindow(dpy, statusWindow->w);722statusWindow->on = False;723return;724}725parent = JNU_CallMethodByName(GetJNIEnv(), NULL, pX11IMData->x11inputmethod,726"getCurrentParentWindow",727"()J").j;728if (statusWindow->parent != parent) {729statusWindow->parent = parent;730}731XGetWindowAttributes(dpy, parent, &xwa);732XTranslateCoordinates(dpy,733parent, xwa.root,734xwa.x, xwa.y,735&x, &y,736&child);737if (statusWindow->x != x ||738statusWindow->y != y ||739statusWindow->height != xwa.height)740{741statusWindow->x = x;742statusWindow->y = y;743statusWindow->height = xwa.height;744x = statusWindow->x - statusWindow->off_x;745y = statusWindow->y + statusWindow->height - statusWindow->off_y;746if (x < 0 ) {747x = 0;748}749if (x + statusWindow->statusW > statusWindow->rootW) {750x = statusWindow->rootW - statusWindow->statusW;751}752if (y + statusWindow->statusH > statusWindow->rootH) {753y = statusWindow->rootH - statusWindow->statusH;754}755XMoveWindow(dpy, statusWindow->w, x, y);756}757statusWindow->on = True;758XMapWindow(dpy, statusWindow->w);759}760761void paintStatusWindow(StatusWindow *statusWindow){762Window win = statusWindow->w;763GC lightgc = statusWindow->lightGC;764GC dimgc = statusWindow->dimGC;765GC bggc = statusWindow->bgGC;766GC fggc = statusWindow->fgGC;767768int width = statusWindow->statusW;769int height = statusWindow->statusH;770int bwidth = statusWindow->bWidth;771XFillRectangle(dpy, win, bggc, 0, 0, width, height);772/* draw border */773XDrawLine(dpy, win, fggc, 0, 0, width, 0);774XDrawLine(dpy, win, fggc, 0, height-1, width-1, height-1);775XDrawLine(dpy, win, fggc, 0, 0, 0, height-1);776XDrawLine(dpy, win, fggc, width-1, 0, width-1, height-1);777778XDrawLine(dpy, win, lightgc, 1, 1, width-bwidth, 1);779XDrawLine(dpy, win, lightgc, 1, 1, 1, height-2);780XDrawLine(dpy, win, lightgc, 1, height-2, width-bwidth, height-2);781XDrawLine(dpy, win, lightgc, width-bwidth-1, 1, width-bwidth-1, height-2);782783XDrawLine(dpy, win, dimgc, 2, 2, 2, height-3);784XDrawLine(dpy, win, dimgc, 2, height-3, width-bwidth-1, height-3);785XDrawLine(dpy, win, dimgc, 2, 2, width-bwidth-2, 2);786XDrawLine(dpy, win, dimgc, width-bwidth, 2, width-bwidth, height-3);787if (statusWindow->fontset) {788XmbDrawString(dpy, win, statusWindow->fontset, fggc,789bwidth + 2, height - bwidth - 4,790statusWindow->status,791strlen(statusWindow->status));792} else {793/*too bad we failed to create a fontset for this locale*/794XDrawString(dpy, win, fggc, bwidth + 2, height - bwidth - 4,795"[InputMethod ON]", strlen("[InputMethod ON]"));796}797}798799static void adjustStatusWindow(Window shell) {800JNIEnv *env = GetJNIEnv();801X11InputMethodData *pX11IMData = NULL;802StatusWindow *statusWindow;803804if (NULL == currentX11InputMethodInstance805|| !isX11InputMethodGRefInList(currentX11InputMethodInstance)806|| NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))807|| NULL == (statusWindow = pX11IMData->statusWindow)808|| !statusWindow->on)809{810return;811}812813{814XWindowAttributes xwa;815int x, y;816Window child;817XGetWindowAttributes(dpy, shell, &xwa);818XTranslateCoordinates(dpy,819shell, xwa.root,820xwa.x, xwa.y,821&x, &y,822&child);823if (statusWindow->x != x824|| statusWindow->y != y825|| statusWindow->height != xwa.height){826statusWindow->x = x;827statusWindow->y = y;828statusWindow->height = xwa.height;829830x = statusWindow->x - statusWindow->off_x;831y = statusWindow->y + statusWindow->height - statusWindow->off_y;832if (x < 0 ) {833x = 0;834}835if (x + statusWindow->statusW > statusWindow->rootW){836x = statusWindow->rootW - statusWindow->statusW;837}838if (y + statusWindow->statusH > statusWindow->rootH){839y = statusWindow->rootH - statusWindow->statusH;840}841XMoveWindow(dpy, statusWindow->w, x, y);842}843}844}845#endif /* __linux__ */846847/*848* Creates two XICs, one for active clients and the other for passive849* clients. All information on those XICs are stored in the850* X11InputMethodData given by the pX11IMData parameter.851*852* For active clients: Try to use preedit callback to support853* on-the-spot. If tc is not null, the XIC to be created will854* share the Status Area with Motif widgets (TextComponents). If the855* preferable styles can't be used, fallback to root-window styles. If856* root-window styles failed, fallback to None styles.857*858* For passive clients: Try to use root-window styles. If failed,859* fallback to None styles.860*/861static Bool862createXIC(JNIEnv * env, X11InputMethodData *pX11IMData, Window w)863{864XVaNestedList preedit = NULL;865XVaNestedList status = NULL;866XIMStyle on_the_spot_styles = XIMPreeditCallbacks,867active_styles = 0,868passive_styles = 0,869no_styles = 0;870XIMCallback *callbacks;871unsigned short i;872XIMStyles *im_styles;873char *ret = NULL;874875if (X11im == NULL) {876return False;877}878if (!w) {879return False;880}881882ret = XGetIMValues(X11im, XNQueryInputStyle, &im_styles, NULL);883884if (ret != NULL) {885jio_fprintf(stderr,"XGetIMValues: %s\n",ret);886return FALSE ;887}888889on_the_spot_styles |= XIMStatusNothing;890891#if defined(__linux__)892/*kinput does not support XIMPreeditCallbacks and XIMStatusArea893at the same time, so use StatusCallback to draw the status894ourself895*/896for (i = 0; i < im_styles->count_styles; i++) {897if (im_styles->supported_styles[i] == (XIMPreeditCallbacks | XIMStatusCallbacks)) {898on_the_spot_styles = (XIMPreeditCallbacks | XIMStatusCallbacks);899break;900}901}902#endif /* __linux__ */903904for (i = 0; i < im_styles->count_styles; i++) {905active_styles |= im_styles->supported_styles[i] & on_the_spot_styles;906passive_styles |= im_styles->supported_styles[i] & ROOT_WINDOW_STYLES;907no_styles |= im_styles->supported_styles[i] & NO_STYLES;908}909910XFree(im_styles);911912if (active_styles != on_the_spot_styles) {913if (passive_styles == ROOT_WINDOW_STYLES)914active_styles = passive_styles;915else {916if (no_styles == NO_STYLES)917active_styles = passive_styles = NO_STYLES;918else919active_styles = passive_styles = 0;920}921} else {922if (passive_styles != ROOT_WINDOW_STYLES) {923if (no_styles == NO_STYLES)924active_styles = passive_styles = NO_STYLES;925else926active_styles = passive_styles = 0;927}928}929930if (active_styles == on_the_spot_styles) {931pX11IMData->ic_passive = XCreateIC(X11im,932XNClientWindow, w,933XNFocusWindow, w,934XNInputStyle, passive_styles,935NULL);936937callbacks = (XIMCallback *)malloc(sizeof(XIMCallback) * NCALLBACKS);938if (callbacks == (XIMCallback *)NULL)939return False;940pX11IMData->callbacks = callbacks;941942for (i = 0; i < NCALLBACKS; i++, callbacks++) {943callbacks->client_data = (XPointer) pX11IMData->x11inputmethod;944callbacks->callback = callback_funcs[i];945}946947callbacks = pX11IMData->callbacks;948preedit = (XVaNestedList)XVaCreateNestedList(0,949XNPreeditStartCallback, &callbacks[PreeditStartIndex],950XNPreeditDoneCallback, &callbacks[PreeditDoneIndex],951XNPreeditDrawCallback, &callbacks[PreeditDrawIndex],952XNPreeditCaretCallback, &callbacks[PreeditCaretIndex],953NULL);954if (preedit == (XVaNestedList)NULL)955goto err;956#if defined(__linux__)957/*always try XIMStatusCallbacks for active client...*/958{959status = (XVaNestedList)XVaCreateNestedList(0,960XNStatusStartCallback, &callbacks[StatusStartIndex],961XNStatusDoneCallback, &callbacks[StatusDoneIndex],962XNStatusDrawCallback, &callbacks[StatusDrawIndex],963NULL);964965if (status == NULL)966goto err;967pX11IMData->statusWindow = createStatusWindow(w);968pX11IMData->ic_active = XCreateIC(X11im,969XNClientWindow, w,970XNFocusWindow, w,971XNInputStyle, active_styles,972XNPreeditAttributes, preedit,973XNStatusAttributes, status,974NULL);975XFree((void *)status);976XFree((void *)preedit);977}978#else /* !__linux__ */979pX11IMData->ic_active = XCreateIC(X11im,980XNClientWindow, w,981XNFocusWindow, w,982XNInputStyle, active_styles,983XNPreeditAttributes, preedit,984NULL);985XFree((void *)preedit);986#endif /* __linux__ */987} else {988pX11IMData->ic_active = XCreateIC(X11im,989XNClientWindow, w,990XNFocusWindow, w,991XNInputStyle, active_styles,992NULL);993pX11IMData->ic_passive = pX11IMData->ic_active;994}995996if (pX11IMData->ic_active == (XIC)0997|| pX11IMData->ic_passive == (XIC)0) {998return False;999}10001001/*1002* Use commit string call back if possible.1003* This will ensure the correct order of preedit text and commit text1004*/1005{1006XIMCallback cb;1007cb.client_data = (XPointer) pX11IMData->x11inputmethod;1008cb.callback = (XIMProc) CommitStringCallback;1009XSetICValues (pX11IMData->ic_active, XNCommitStringCallback, &cb, NULL);1010if (pX11IMData->ic_active != pX11IMData->ic_passive) {1011XSetICValues (pX11IMData->ic_passive, XNCommitStringCallback, &cb, NULL);1012}1013}10141015// The code set the IC mode that the preedit state is not initialied1016// at XmbResetIC. This attribute can be set at XCreateIC. I separately1017// set the attribute to avoid the failure of XCreateIC at some platform1018// which does not support the attribute.1019if (pX11IMData->ic_active != 0)1020XSetICValues(pX11IMData->ic_active,1021XNResetState, XIMInitialState,1022NULL);1023if (pX11IMData->ic_passive != 01024&& pX11IMData->ic_active != pX11IMData->ic_passive)1025XSetICValues(pX11IMData->ic_passive,1026XNResetState, XIMInitialState,1027NULL);10281029/* Add the global reference object to X11InputMethod to the list. */1030addToX11InputMethodGRefList(pX11IMData->x11inputmethod);10311032/* Unset focus to avoid unexpected IM on */1033setXICFocus(pX11IMData->ic_active, False);1034if (pX11IMData->ic_active != pX11IMData->ic_passive)1035setXICFocus(pX11IMData->ic_passive, False);10361037return True;10381039err:1040if (preedit)1041XFree((void *)preedit);1042THROW_OUT_OF_MEMORY_ERROR();1043return False;1044}10451046static int1047PreeditStartCallback(XIC ic, XPointer client_data, XPointer call_data)1048{1049/*ARGSUSED*/1050/* printf("Native: PreeditStartCallback\n"); */1051return -1;1052}10531054static void1055PreeditDoneCallback(XIC ic, XPointer client_data, XPointer call_data)1056{1057/*ARGSUSED*/1058/* printf("Native: PreeditDoneCallback\n"); */1059}10601061/*1062* Translate the preedit draw callback items to Java values and invoke1063* X11InputMethod.dispatchComposedText().1064*1065* client_data: X11InputMethod object1066*/1067static void1068PreeditDrawCallback(XIC ic, XPointer client_data,1069XIMPreeditDrawCallbackStruct *pre_draw)1070{1071JNIEnv *env = GetJNIEnv();1072X11InputMethodData *pX11IMData = NULL;1073jmethodID x11imMethodID;10741075XIMText *text;1076jstring javastr = NULL;1077jintArray style = NULL;10781079/* printf("Native: PreeditDrawCallback() \n"); */1080if (pre_draw == NULL) {1081return;1082}1083AWT_LOCK();1084if (!isX11InputMethodGRefInList((jobject)client_data)) {1085if ((jobject)client_data == currentX11InputMethodInstance) {1086currentX11InputMethodInstance = NULL;1087}1088goto finally;1089}1090if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) {1091goto finally;1092}10931094if ((text = pre_draw->text) != NULL) {1095if (text->string.multi_byte != NULL) {1096if (pre_draw->text->encoding_is_wchar == False) {1097javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte);1098if (javastr == NULL) {1099goto finally;1100}1101} else {1102char *mbstr = wcstombsdmp(text->string.wide_char, text->length);1103if (mbstr == NULL) {1104goto finally;1105}1106javastr = JNU_NewStringPlatform(env, (const char *)mbstr);1107free(mbstr);1108if (javastr == NULL) {1109goto finally;1110}1111}1112}1113if (text->feedback != NULL) {1114int cnt;1115jint *tmpstyle;11161117style = (*env)->NewIntArray(env, text->length);1118if (JNU_IsNull(env, style)) {1119(*env)->ExceptionClear(env);1120THROW_OUT_OF_MEMORY_ERROR();1121goto finally;1122}11231124if (sizeof(XIMFeedback) == sizeof(jint)) {1125/*1126* Optimization to avoid copying the array1127*/1128(*env)->SetIntArrayRegion(env, style, 0,1129text->length, (jint *)text->feedback);1130} else {1131tmpstyle = (jint *)malloc(sizeof(jint)*(text->length));1132if (tmpstyle == (jint *) NULL) {1133THROW_OUT_OF_MEMORY_ERROR();1134goto finally;1135}1136for (cnt = 0; cnt < (int)text->length; cnt++)1137tmpstyle[cnt] = text->feedback[cnt];1138(*env)->SetIntArrayRegion(env, style, 0,1139text->length, (jint *)tmpstyle);1140free(tmpstyle);1141}1142}1143}1144JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,1145"dispatchComposedText",1146"(Ljava/lang/String;[IIIIJ)V",1147javastr,1148style,1149(jint)pre_draw->chg_first,1150(jint)pre_draw->chg_length,1151(jint)pre_draw->caret,1152awt_util_nowMillisUTC());1153finally:1154AWT_UNLOCK();1155return;1156}11571158static void1159PreeditCaretCallback(XIC ic, XPointer client_data,1160XIMPreeditCaretCallbackStruct *pre_caret)1161{1162/*ARGSUSED*/1163/* printf("Native: PreeditCaretCallback\n"); */1164}11651166#if defined(__linux__)1167static void1168StatusStartCallback(XIC ic, XPointer client_data, XPointer call_data)1169{1170/*ARGSUSED*/1171/*printf("StatusStartCallback:\n"); */1172}11731174static void1175StatusDoneCallback(XIC ic, XPointer client_data, XPointer call_data)1176{1177/*ARGSUSED*/1178/*printf("StatusDoneCallback:\n"); */1179JNIEnv *env = GetJNIEnv();1180X11InputMethodData *pX11IMData = NULL;1181StatusWindow *statusWindow;11821183AWT_LOCK();11841185if (!isX11InputMethodGRefInList((jobject)client_data)) {1186if ((jobject)client_data == currentX11InputMethodInstance) {1187currentX11InputMethodInstance = NULL;1188}1189goto finally;1190}11911192if (NULL == (pX11IMData = getX11InputMethodData(env, (jobject)client_data))1193|| NULL == (statusWindow = pX11IMData->statusWindow)){1194goto finally;1195}1196currentX11InputMethodInstance = (jobject)client_data;11971198onoffStatusWindow(pX11IMData, 0, False);11991200finally:1201AWT_UNLOCK();1202}12031204static void1205StatusDrawCallback(XIC ic, XPointer client_data,1206XIMStatusDrawCallbackStruct *status_draw)1207{1208/*ARGSUSED*/1209/*printf("StatusDrawCallback:\n"); */1210JNIEnv *env = GetJNIEnv();1211X11InputMethodData *pX11IMData = NULL;1212StatusWindow *statusWindow;12131214AWT_LOCK();12151216if (!isX11InputMethodGRefInList((jobject)client_data)) {1217if ((jobject)client_data == currentX11InputMethodInstance) {1218currentX11InputMethodInstance = NULL;1219}1220goto finally;1221}12221223if (NULL == (pX11IMData = getX11InputMethodData(env, (jobject)client_data))1224|| NULL == (statusWindow = pX11IMData->statusWindow)){1225goto finally;1226}1227currentX11InputMethodInstance = (jobject)client_data;12281229if (status_draw->type == XIMTextType) {1230XIMText *text = (status_draw->data).text;1231if (text != NULL) {1232if (text->string.multi_byte != NULL) {1233strncpy(statusWindow->status, text->string.multi_byte, MAX_STATUS_LEN);1234statusWindow->status[MAX_STATUS_LEN - 1] = '\0';1235} else {1236char *mbstr = wcstombsdmp(text->string.wide_char, text->length);1237if (mbstr == NULL) {1238goto finally;1239}1240strncpy(statusWindow->status, mbstr, MAX_STATUS_LEN);1241statusWindow->status[MAX_STATUS_LEN - 1] = '\0';1242free(mbstr);1243}1244statusWindow->on = True;1245onoffStatusWindow(pX11IMData, statusWindow->parent, True);1246paintStatusWindow(statusWindow);1247} else {1248statusWindow->on = False;1249/*just turnoff the status window1250paintStatusWindow(statusWindow);1251*/1252onoffStatusWindow(pX11IMData, 0, False);1253}1254}12551256finally:1257AWT_UNLOCK();1258}1259#endif /* __linux__ */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) {1326if (getX11InputMethodData(env,1327x11InputMethodGRefListHead->inputMethodGRef) == NULL) {1328/* Clear possible exceptions1329*/1330if ((*env)->ExceptionOccurred(env)) {1331(*env)->ExceptionDescribe(env);1332(*env)->ExceptionClear(env);1333}1334}1335}1336AWT_UNLOCK();1337}13381339JNIEXPORT jboolean JNICALL1340Java_sun_awt_X11_XInputMethod_openXIMNative(JNIEnv *env,1341jobject this,1342jlong display)1343{1344Bool registered;13451346AWT_LOCK();13471348dpy = (Display *)jlong_to_ptr(display);13491350/* Use IMInstantiate call back only on Linux, as there is a bug in Solaris1351(4768335)1352*/1353#if defined(__linux__)1354registered = XRegisterIMInstantiateCallback(dpy, NULL, NULL,1355NULL, (XIDProc)OpenXIMCallback, NULL);1356if (!registered) {1357/* directly call openXIM callback */1358#endif1359OpenXIMCallback(dpy, NULL, NULL);1360#if defined(__linux__)1361}1362#endif13631364AWT_UNLOCK();13651366return JNI_TRUE;1367}13681369JNIEXPORT jboolean JNICALL1370Java_sun_awt_X11_XInputMethod_createXICNative(JNIEnv *env,1371jobject this,1372jlong window)1373{1374X11InputMethodData *pX11IMData;1375jobject globalRef;1376XIC ic;13771378AWT_LOCK();13791380if (!window) {1381JNU_ThrowNullPointerException(env, "NullPointerException");1382AWT_UNLOCK();1383return JNI_FALSE;1384}13851386pX11IMData = (X11InputMethodData *) calloc(1, sizeof(X11InputMethodData));1387if (pX11IMData == NULL) {1388THROW_OUT_OF_MEMORY_ERROR();1389AWT_UNLOCK();1390return JNI_FALSE;1391}13921393globalRef = (*env)->NewGlobalRef(env, this);1394pX11IMData->x11inputmethod = globalRef;1395#if defined(__linux__)1396pX11IMData->statusWindow = NULL;1397#endif /* __linux__ */13981399pX11IMData->lookup_buf = 0;1400pX11IMData->lookup_buf_len = 0;14011402if (createXIC(env, pX11IMData, (Window)window) == False) {1403destroyX11InputMethodData((JNIEnv *) NULL, pX11IMData);1404pX11IMData = (X11InputMethodData *) NULL;1405if ((*env)->ExceptionCheck(env)) {1406goto finally;1407}1408}14091410setX11InputMethodData(env, this, pX11IMData);14111412finally:1413AWT_UNLOCK();1414return (pX11IMData != NULL);1415}14161417JNIEXPORT void JNICALL1418Java_sun_awt_X11_XInputMethod_setXICFocusNative(JNIEnv *env,1419jobject this,1420jlong w,1421jboolean req,1422jboolean active)1423{1424X11InputMethodData *pX11IMData;1425AWT_LOCK();1426pX11IMData = getX11InputMethodData(env, this);1427if (pX11IMData == NULL) {1428AWT_UNLOCK();1429return;1430}14311432if (req) {1433if (!w) {1434AWT_UNLOCK();1435return;1436}1437pX11IMData->current_ic = active ?1438pX11IMData->ic_active : pX11IMData->ic_passive;1439/*1440* On Solaris2.6, setXICWindowFocus() has to be invoked1441* before setting focus.1442*/1443setXICWindowFocus(pX11IMData->current_ic, w);1444setXICFocus(pX11IMData->current_ic, req);1445currentX11InputMethodInstance = pX11IMData->x11inputmethod;1446currentFocusWindow = w;1447#if defined(__linux__)1448if (active && pX11IMData->statusWindow && pX11IMData->statusWindow->on)1449onoffStatusWindow(pX11IMData, w, True);1450#endif1451} else {1452currentX11InputMethodInstance = NULL;1453currentFocusWindow = 0;1454#if defined(__linux__)1455onoffStatusWindow(pX11IMData, 0, False);1456if (pX11IMData->current_ic != NULL)1457#endif1458setXICFocus(pX11IMData->current_ic, req);14591460pX11IMData->current_ic = (XIC)0;1461}14621463XFlush(dpy);1464AWT_UNLOCK();1465}14661467/*1468* Class: sun_awt_X11InputMethodBase1469* Method: initIDs1470* Signature: ()V1471* This function gets called from the static initializer for1472* X11InputMethod.java to initialize the fieldIDs for fields1473* that may be accessed from C1474*/1475JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_initIDs1476(JNIEnv *env, jclass cls)1477{1478x11InputMethodIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J");1479}14801481/*1482* Class: sun_awt_X11InputMethodBase1483* Method: turnoffStatusWindow1484* Signature: ()V1485*/1486JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_turnoffStatusWindow1487(JNIEnv *env, jobject this)1488{1489#if defined(__linux__)1490X11InputMethodData *pX11IMData;1491StatusWindow *statusWindow;14921493AWT_LOCK();14941495if (NULL == currentX11InputMethodInstance1496|| !isX11InputMethodGRefInList(currentX11InputMethodInstance)1497|| NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))1498|| NULL == (statusWindow = pX11IMData->statusWindow)1499|| !statusWindow->on ){1500AWT_UNLOCK();1501return;1502}1503onoffStatusWindow(pX11IMData, 0, False);15041505AWT_UNLOCK();1506#endif1507}15081509/*1510* Class: sun_awt_X11InputMethodBase1511* Method: disposeXIC1512* Signature: ()V1513*/1514JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_disposeXIC1515(JNIEnv *env, jobject this)1516{1517X11InputMethodData *pX11IMData = NULL;15181519AWT_LOCK();1520pX11IMData = getX11InputMethodData(env, this);1521if (pX11IMData == NULL) {1522AWT_UNLOCK();1523return;1524}15251526setX11InputMethodData(env, this, NULL);15271528if (pX11IMData->x11inputmethod == currentX11InputMethodInstance) {1529currentX11InputMethodInstance = NULL;1530currentFocusWindow = 0;1531}1532destroyX11InputMethodData(env, pX11IMData);1533AWT_UNLOCK();1534}15351536/*1537* Class: sun_awt_X11InputMethodBase1538* Method: resetXIC1539* Signature: ()Ljava/lang/String;1540*/1541JNIEXPORT jstring JNICALL Java_sun_awt_X11InputMethodBase_resetXIC1542(JNIEnv *env, jobject this)1543{1544X11InputMethodData *pX11IMData;1545char *xText = NULL;1546jstring jText = (jstring)0;15471548AWT_LOCK();1549pX11IMData = getX11InputMethodData(env, this);1550if (pX11IMData == NULL) {1551AWT_UNLOCK();1552return jText;1553}15541555if (pX11IMData->current_ic)1556xText = XmbResetIC(pX11IMData->current_ic);1557else {1558/*1559* If there is no reference to the current XIC, try to reset both XICs.1560*/1561xText = XmbResetIC(pX11IMData->ic_active);1562/*it may also means that the real client component does1563not have focus -- has been deactivated... its xic should1564not have the focus, bug#4284651 showes reset XIC for htt1565may bring the focus back, so de-focus it again.1566*/1567setXICFocus(pX11IMData->ic_active, FALSE);1568if (pX11IMData->ic_active != pX11IMData->ic_passive) {1569char *tmpText = XmbResetIC(pX11IMData->ic_passive);1570setXICFocus(pX11IMData->ic_passive, FALSE);1571if (xText == (char *)NULL && tmpText)1572xText = tmpText;1573}15741575}1576if (xText != NULL) {1577jText = JNU_NewStringPlatform(env, (const char *)xText);1578XFree((void *)xText);1579}15801581AWT_UNLOCK();1582return jText;1583}15841585/*1586* Class: sun_awt_X11InputMethodBase1587* Method: setCompositionEnabledNative1588* Signature: (Z)Z1589*1590* This method tries to set the XNPreeditState attribute associated with the current1591* XIC to the passed in 'enable' state.1592*1593* Return JNI_TRUE if XNPreeditState attribute is successfully changed to the1594* 'enable' state; Otherwise, if XSetICValues fails to set this attribute,1595* java.lang.UnsupportedOperationException will be thrown. JNI_FALSE is returned if this1596* method fails due to other reasons.1597*/1598JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_setCompositionEnabledNative1599(JNIEnv *env, jobject this, jboolean enable)1600{1601X11InputMethodData *pX11IMData;1602char * ret = NULL;1603XVaNestedList pr_atrb;1604#if defined(__linux__)1605Boolean calledXSetICFocus = False;1606#endif16071608AWT_LOCK();1609pX11IMData = getX11InputMethodData(env, this);16101611if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) {1612AWT_UNLOCK();1613return JNI_FALSE;1614}16151616#if defined(__linux__)1617if (NULL != pX11IMData->statusWindow) {1618Window focus = 0;1619int revert_to;1620#if defined(_LP64) && !defined(_LITTLE_ENDIAN)1621// The Window value which is used for XGetICValues must be 32bit on BigEndian XOrg's xlib1622unsigned int w = 0;1623#else1624Window w = 0;1625#endif1626XGetInputFocus(awt_display, &focus, &revert_to);1627XGetICValues(pX11IMData->current_ic, XNFocusWindow, &w, NULL);1628if (RevertToPointerRoot == revert_to1629&& pX11IMData->ic_active != pX11IMData->ic_passive) {1630if (pX11IMData->current_ic == pX11IMData->ic_active) {1631if (getParentWindow(focus) == getParentWindow(w)) {1632XUnsetICFocus(pX11IMData->ic_active);1633calledXSetICFocus = True;1634}1635}1636}1637}1638#endif1639pr_atrb = XVaCreateNestedList(0,1640XNPreeditState, (enable ? XIMPreeditEnable : XIMPreeditDisable),1641NULL);1642ret = XSetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL);1643XFree((void *)pr_atrb);1644#if defined(__linux__)1645if (calledXSetICFocus) {1646XSetICFocus(pX11IMData->ic_active);1647}1648#endif1649AWT_UNLOCK();16501651if ((ret != 0)1652&& ((strcmp(ret, XNPreeditAttributes) == 0)1653|| (strcmp(ret, XNPreeditState) == 0))) {1654JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");1655}16561657return (jboolean)(ret == 0);1658}16591660/*1661* Class: sun_awt_X11InputMethodBase1662* Method: isCompositionEnabledNative1663* Signature: ()Z1664*1665* This method tries to get the XNPreeditState attribute associated with the current XIC.1666*1667* Return JNI_TRUE if the XNPreeditState is successfully retrieved. Otherwise, if1668* XGetICValues fails to get this attribute, java.lang.UnsupportedOperationException1669* will be thrown. JNI_FALSE is returned if this method fails due to other reasons.1670*/1671JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_isCompositionEnabledNative1672(JNIEnv *env, jobject this)1673{1674X11InputMethodData *pX11IMData = NULL;1675char * ret = NULL;1676#if defined(__linux__) && defined(_LP64) && !defined(_LITTLE_ENDIAN)1677// XIMPreeditState value which is used for XGetICValues must be 32bit on BigEndian XOrg's xlib1678unsigned int state = XIMPreeditUnKnown;1679#else1680XIMPreeditState state = XIMPreeditUnKnown;1681#endif16821683XVaNestedList pr_atrb;16841685AWT_LOCK();1686pX11IMData = getX11InputMethodData(env, this);16871688if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) {1689AWT_UNLOCK();1690return JNI_FALSE;1691}16921693pr_atrb = XVaCreateNestedList(0, XNPreeditState, &state, NULL);1694ret = XGetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL);1695XFree((void *)pr_atrb);1696AWT_UNLOCK();16971698if ((ret != 0)1699&& ((strcmp(ret, XNPreeditAttributes) == 0)1700|| (strcmp(ret, XNPreeditState) == 0))) {1701JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");1702return JNI_FALSE;1703}17041705return (jboolean)(state == XIMPreeditEnable);1706}17071708JNIEXPORT void JNICALL Java_sun_awt_X11_XInputMethod_adjustStatusWindow1709(JNIEnv *env, jobject this, jlong window)1710{1711#if defined(__linux__)1712AWT_LOCK();1713adjustStatusWindow(window);1714AWT_UNLOCK();1715#endif1716}17171718#if defined(__linux__)1719static Window getParentWindow(Window w)1720{1721Window root=None, parent=None, *ignore_children=NULL;1722unsigned int ignore_uint=0;1723Status status = 0;17241725if (w == None)1726return None;1727status = XQueryTree(dpy, w, &root, &parent, &ignore_children, &ignore_uint);1728XFree(ignore_children);1729if (status == 0)1730return None;1731return parent;1732}1733#endif173417351736