< prev index next >

src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c

Print this page
rev 50285 : 8201429: Support AIX Input Method Editor (IME) for AWT Input Method Framework (IMF)

*** 1,7 **** /* ! * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 25,119 **** #ifdef HEADLESS #error This file should not be included in headless library #endif - #include <stdio.h> - #include <stdlib.h> - #include <X11/Xlib.h> - #include <X11/keysym.h> - #include <sys/time.h> - #include "awt.h" #include "awt_p.h" #include <sun_awt_X11InputMethod.h> #include <sun_awt_X11_XInputMethod.h> #define THROW_OUT_OF_MEMORY_ERROR() \ JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL) struct X11InputMethodIDs { jfieldID pData; } x11InputMethodIDs; ! static void PreeditStartCallback(XIC, XPointer, XPointer); static void PreeditDoneCallback(XIC, XPointer, XPointer); static void PreeditDrawCallback(XIC, XPointer, XIMPreeditDrawCallbackStruct *); static void PreeditCaretCallback(XIC, XPointer, XIMPreeditCaretCallbackStruct *); - #if defined(__linux__) || defined(MACOSX) static void StatusStartCallback(XIC, XPointer, XPointer); static void StatusDoneCallback(XIC, XPointer, XPointer); static void StatusDrawCallback(XIC, XPointer, XIMStatusDrawCallbackStruct *); - #endif #define ROOT_WINDOW_STYLES (XIMPreeditNothing | XIMStatusNothing) #define NO_STYLES (XIMPreeditNone | XIMStatusNone) #define PreeditStartIndex 0 #define PreeditDoneIndex 1 #define PreeditDrawIndex 2 #define PreeditCaretIndex 3 - #if defined(__linux__) || defined(MACOSX) #define StatusStartIndex 4 #define StatusDoneIndex 5 #define StatusDrawIndex 6 #define NCALLBACKS 7 ! #else ! #define NCALLBACKS 4 ! #endif /* * Callback function pointers: the order has to match the *Index * values above. */ static XIMProc callback_funcs[NCALLBACKS] = { (XIMProc)PreeditStartCallback, (XIMProc)PreeditDoneCallback, (XIMProc)PreeditDrawCallback, (XIMProc)PreeditCaretCallback, - #if defined(__linux__) || defined(MACOSX) (XIMProc)StatusStartCallback, (XIMProc)StatusDoneCallback, (XIMProc)StatusDrawCallback, - #endif }; - #if defined(__linux__) || defined(MACOSX) #define MAX_STATUS_LEN 100 typedef struct { Window w; /*status window id */ Window root; /*the root window id */ Window parent; /*parent shell window */ int x, y; /*parent's upperleft position */ int width, height; /*parent's width, height */ GC lightGC; /*gc for light border */ GC dimGC; /*gc for dim border */ GC bgGC; /*normal painting */ GC fgGC; /*normal painting */ int statusW, statusH; /*status window's w, h */ int rootW, rootH; /*root window's w, h */ int bWidth; /*border width */ ! char status[MAX_STATUS_LEN]; /*status text */ XFontSet fontset; /*fontset for drawing */ int off_x, off_y; Bool on; /*if the status window on*/ } StatusWindow; - #endif /* * X11InputMethodData keeps per X11InputMethod instance information. A pointer * to this data structure is kept in an X11InputMethod object (pData). */ --- 25,131 ---- #ifdef HEADLESS #error This file should not be included in headless library #endif #include "awt.h" #include "awt_p.h" + #include <sun_awt_X11InputMethodBase.h> #include <sun_awt_X11InputMethod.h> #include <sun_awt_X11_XInputMethod.h> + #include <langinfo.h> + #include <stdio.h> + #include <stdlib.h> + #include <sys/time.h> + #include <wchar.h> + #include <wctype.h> + #include <X11/Intrinsic.h> + #include <X11/keysym.h> + #include <X11/Xlib.h> + #define THROW_OUT_OF_MEMORY_ERROR() \ JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL) struct X11InputMethodIDs { jfieldID pData; } x11InputMethodIDs; ! static int PreeditStartCallback(XIC, XPointer, XPointer); static void PreeditDoneCallback(XIC, XPointer, XPointer); static void PreeditDrawCallback(XIC, XPointer, XIMPreeditDrawCallbackStruct *); static void PreeditCaretCallback(XIC, XPointer, XIMPreeditCaretCallbackStruct *); static void StatusStartCallback(XIC, XPointer, XPointer); static void StatusDoneCallback(XIC, XPointer, XPointer); static void StatusDrawCallback(XIC, XPointer, XIMStatusDrawCallbackStruct *); #define ROOT_WINDOW_STYLES (XIMPreeditNothing | XIMStatusNothing) #define NO_STYLES (XIMPreeditNone | XIMStatusNone) + /* added style to allow for in-place composition, such as "dead" keys for accents */ + #define IN_PLACE_STYLES (XIMPreeditNothing | XIMStatusNone) #define PreeditStartIndex 0 #define PreeditDoneIndex 1 #define PreeditDrawIndex 2 #define PreeditCaretIndex 3 #define StatusStartIndex 4 #define StatusDoneIndex 5 #define StatusDrawIndex 6 #define NCALLBACKS 7 ! ! #define STATUS_BORDER 2 /* Status Border width */ ! #define CARET_OFFSET 1 /* Offset of caret position (pixel) */ ! #define BORDER_MARGIN 3 /* BORDER MARGIN width */ ! #define STATUS_MARGIN 7 /* Margin between the status window and its parent window */ ! #define PREEDIT_ATTR_MASK (XIMReverse|XIMUnderline) ! /* Preedit attribute which host adapter can handle */ /* * Callback function pointers: the order has to match the *Index * values above. */ static XIMProc callback_funcs[NCALLBACKS] = { (XIMProc)PreeditStartCallback, (XIMProc)PreeditDoneCallback, (XIMProc)PreeditDrawCallback, (XIMProc)PreeditCaretCallback, (XIMProc)StatusStartCallback, (XIMProc)StatusDoneCallback, (XIMProc)StatusDrawCallback, }; #define MAX_STATUS_LEN 100 typedef struct { Window w; /*status window id */ Window root; /*the root window id */ Window parent; /*parent shell window */ + Window grandParent; /*window has WM frame */ int x, y; /*parent's upperleft position */ int width, height; /*parent's width, height */ GC lightGC; /*gc for light border */ GC dimGC; /*gc for dim border */ GC bgGC; /*normal painting */ GC fgGC; /*normal painting */ int statusW, statusH; /*status window's w, h */ int rootW, rootH; /*root window's w, h */ int bWidth; /*border width */ ! wchar_t status[MAX_STATUS_LEN + 1]; /*status text */ XFontSet fontset; /*fontset for drawing */ int off_x, off_y; Bool on; /*if the status window on*/ + int fOff; /* font base line(in pixel) from top */ + int fBot; /* font bottom line(in pixel) from top */ + int peTextW; /* Composition text width in pixel */ + wchar_t* peText; /* Composed string (wide char.) */ + XIMFeedback* peAttr; /* Composed text attribute */ + int peCaret; /* Caret position in number of character */ + Bool status_ready; /* Not draw Status at XCreateIC */ } StatusWindow; /* * X11InputMethodData keeps per X11InputMethod instance information. A pointer * to this data structure is kept in an X11InputMethod object (pData). */
*** 122,158 **** XIC ic_active; /* X Input Context for active clients */ XIC ic_passive; /* X Input Context for passive clients */ XIMCallback *callbacks; /* callback parameters */ jobject x11inputmethod; /* global ref to X11InputMethod instance */ /* associated with the XIC */ - #if defined(__linux__) || defined(MACOSX) StatusWindow *statusWindow; /* our own status window */ ! #endif ! char *lookup_buf; /* buffer used for XmbLookupString */ ! int lookup_buf_len; /* lookup buffer size in bytes */ } X11InputMethodData; - /* - * When XIC is created, a global reference is created for - * sun.awt.X11InputMethod object so that it could be used by the XIM callback - * functions. This could be a dangerous thing to do when the original - * X11InputMethod object is garbage collected and as a result, - * destroyX11InputMethodData is called to delete the global reference. - * If any XIM callback function still holds and uses the "already deleted" - * global reference, disaster is going to happen. So we have to maintain - * a list for these global references which is consulted first when the - * callback functions or any function tries to use "currentX11InputMethodObject" - * which always refers to the global reference try to use it. - * - */ - typedef struct _X11InputMethodGRefNode { - jobject inputMethodGRef; - struct _X11InputMethodGRefNode* next; - } X11InputMethodGRefNode; - - X11InputMethodGRefNode *x11InputMethodGRefListHead = NULL; - /* reference to the current X11InputMethod instance, it is always point to the global reference to the X11InputMethodObject since it could be referenced by different threads. */ jobject currentX11InputMethodInstance = NULL; --- 134,149 ---- XIC ic_active; /* X Input Context for active clients */ XIC ic_passive; /* X Input Context for passive clients */ XIMCallback *callbacks; /* callback parameters */ jobject x11inputmethod; /* global ref to X11InputMethod instance */ /* associated with the XIC */ StatusWindow *statusWindow; /* our own status window */ ! Bool passiveStatusWindow;/* Passive Client uses StatusWindow */ ! Bool isActiveClient; /* True:clinet is active */ ! Bool forceReset; /* True: call resetXIC before UnsetICFocus */ } X11InputMethodData; /* reference to the current X11InputMethod instance, it is always point to the global reference to the X11InputMethodObject since it could be referenced by different threads. */ jobject currentX11InputMethodInstance = NULL;
*** 163,191 **** static XIM X11im = NULL; Display * dpy = NULL; #define GetJNIEnv() (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2) - static void DestroyXIMCallback(XIM, XPointer, XPointer); - static void OpenXIMCallback(Display *, XPointer, XPointer); - /* Solaris XIM Extention */ - #define XNCommitStringCallback "commitStringCallback" - static void CommitStringCallback(XIC, XPointer, XPointer); - static X11InputMethodData * getX11InputMethodData(JNIEnv *, jobject); static void setX11InputMethodData(JNIEnv *, jobject, X11InputMethodData *); static void destroyX11InputMethodData(JNIEnv *, X11InputMethodData *); static void freeX11InputMethodData(JNIEnv *, X11InputMethodData *); ! #ifdef __solaris__ ! /* Prototype for this function is missing in Solaris X11R6 Xlib.h */ extern char *XSetIMValues( #if NeedVarargsPrototypes XIM /* im */, ... #endif ); ! #endif /* * This function is stolen from /src/solaris/hpi/src/system_md.c * It is used in setting the time in Java-level InputEvents */ --- 154,198 ---- static XIM X11im = NULL; Display * dpy = NULL; #define GetJNIEnv() (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2) static X11InputMethodData * getX11InputMethodData(JNIEnv *, jobject); static void setX11InputMethodData(JNIEnv *, jobject, X11InputMethodData *); static void destroyX11InputMethodData(JNIEnv *, X11InputMethodData *); static void freeX11InputMethodData(JNIEnv *, X11InputMethodData *); ! /* Prototype for this function is missing in AIX Xlib.h */ extern char *XSetIMValues( #if NeedVarargsPrototypes XIM /* im */, ... #endif ); ! ! static int st_wcslen(wchar_t *string); ! static Bool isPreeditStateActive(XIC ic); ! static void * buf_insert(void * src, void * insert, int size, ! int src_len, int ins_len, int offset); ! static void * handle_buffer(void * source, void * insert, ! int size, int src_len, int ins_len, ! int del_len, int offset); ! static void preedit_draw_passive(X11InputMethodData *pX11IMData, ! XIMPreeditDrawCallbackStruct *pre_draw); ! static void resetPassivePreeditText(StatusWindow *statusWindow); ! static void draw_caret(StatusWindow *statusWindow, GC gc, int pos); ! static int get_next_attr(int len, unsigned long *attr); ! static void draw_preedit(StatusWindow *statusWindow); ! static void align_status(StatusWindow *statusWindow); ! static void shrink_status(StatusWindow *statusWindow); ! static GC create_gc(Window win, Bool isReverse); ! static XFontSet create_fontset(void); ! static Bool is_text_available(XIMText * text); ! static Bool isNativeIm(); ! static Window getGrandParent(Window parent); ! static void moveStatusWindow(StatusWindow *statusWindow); ! static void arrange_window_stack(StatusWindow* statusWindow); ! static Window get_current_focus(XIC ic); /* * This function is stolen from /src/solaris/hpi/src/system_md.c * It is used in setting the time in Java-level InputEvents */
*** 227,317 **** } return mbs; } - /* - * Returns True if the global reference is still in the list, - * otherwise False. - */ - static Bool isX11InputMethodGRefInList(jobject imGRef) { - X11InputMethodGRefNode *pX11InputMethodGRef = x11InputMethodGRefListHead; - - if (imGRef == NULL) { - return False; - } - - while (pX11InputMethodGRef != NULL) { - if (pX11InputMethodGRef->inputMethodGRef == imGRef) { - return True; - } - pX11InputMethodGRef = pX11InputMethodGRef->next; - } - - return False; - } - - /* - * Add the new created global reference to the list. - */ - static void addToX11InputMethodGRefList(jobject newX11InputMethodGRef) { - X11InputMethodGRefNode *newNode = NULL; - - if (newX11InputMethodGRef == NULL || - isX11InputMethodGRefInList(newX11InputMethodGRef)) { - return; - } - - newNode = (X11InputMethodGRefNode *)malloc(sizeof(X11InputMethodGRefNode)); - - if (newNode == NULL) { - return; - } else { - newNode->inputMethodGRef = newX11InputMethodGRef; - newNode->next = x11InputMethodGRefListHead; - x11InputMethodGRefListHead = newNode; - } - } - - /* - * Remove the global reference from the list. - */ - static void removeX11InputMethodGRefFromList(jobject x11InputMethodGRef) { - X11InputMethodGRefNode *pX11InputMethodGRef = NULL; - X11InputMethodGRefNode *cX11InputMethodGRef = x11InputMethodGRefListHead; - - if (x11InputMethodGRefListHead == NULL || - x11InputMethodGRef == NULL) { - return; - } - - /* cX11InputMethodGRef always refers to the current node while - pX11InputMethodGRef refers to the previous node. - */ - while (cX11InputMethodGRef != NULL) { - if (cX11InputMethodGRef->inputMethodGRef == x11InputMethodGRef) { - break; - } - pX11InputMethodGRef = cX11InputMethodGRef; - cX11InputMethodGRef = cX11InputMethodGRef->next; - } - - if (cX11InputMethodGRef == NULL) { - return; /* Not found. */ - } - - if (cX11InputMethodGRef == x11InputMethodGRefListHead) { - x11InputMethodGRefListHead = x11InputMethodGRefListHead->next; - } else { - pX11InputMethodGRef->next = cX11InputMethodGRef->next; - } - free(cX11InputMethodGRef); - - return; - } - - static X11InputMethodData * getX11InputMethodData(JNIEnv * env, jobject imInstance) { X11InputMethodData *pX11IMData = (X11InputMethodData *)JNU_GetLongFieldAsPtr(env, imInstance, x11InputMethodIDs.pData); /* --- 234,243 ----
*** 370,409 **** } static void freeX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData) { - #if defined(__linux__) || defined(MACOSX) if (pX11IMData->statusWindow != NULL){ StatusWindow *sw = pX11IMData->statusWindow; XFreeGC(awt_display, sw->lightGC); XFreeGC(awt_display, sw->dimGC); XFreeGC(awt_display, sw->bgGC); XFreeGC(awt_display, sw->fgGC); if (sw->fontset != NULL) { XFreeFontSet(awt_display, sw->fontset); } XDestroyWindow(awt_display, sw->w); free((void*)sw); } - #endif if (pX11IMData->callbacks) free((void *)pX11IMData->callbacks); if (env) { - /* Remove the global reference from the list, so that - the callback function or whoever refers to it could know. - */ - removeX11InputMethodGRefFromList(pX11IMData->x11inputmethod); (*env)->DeleteGlobalRef(env, pX11IMData->x11inputmethod); } - if (pX11IMData->lookup_buf) { - free((void *)pX11IMData->lookup_buf); - } - free((void *)pX11IMData); } /* * Sets or unsets the focus to the given XIC. --- 296,333 ---- } static void freeX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData) { if (pX11IMData->statusWindow != NULL){ StatusWindow *sw = pX11IMData->statusWindow; XFreeGC(awt_display, sw->lightGC); XFreeGC(awt_display, sw->dimGC); XFreeGC(awt_display, sw->bgGC); XFreeGC(awt_display, sw->fgGC); if (sw->fontset != NULL) { XFreeFontSet(awt_display, sw->fontset); } XDestroyWindow(awt_display, sw->w); + if (pX11IMData->statusWindow->peText){ + free((void *)pX11IMData->statusWindow->peText); + pX11IMData->statusWindow->peText = NULL; + } + if (pX11IMData->statusWindow->peAttr){ + free((void *)pX11IMData->statusWindow->peAttr); + pX11IMData->statusWindow->peAttr = NULL; + } free((void*)sw); } if (pX11IMData->callbacks) free((void *)pX11IMData->callbacks); if (env) { (*env)->DeleteGlobalRef(env, pX11IMData->x11inputmethod); } free((void *)pX11IMData); } /* * Sets or unsets the focus to the given XIC.
*** 453,462 **** --- 377,389 ---- Boolean awt_x11inputmethod_lookupString(XKeyPressedEvent *event, KeySym *keysymp) { JNIEnv *env = GetJNIEnv(); X11InputMethodData *pX11IMData = NULL; + int buf_len = INITIAL_LOOKUP_BUF_SIZE; + char mbbuf[INITIAL_LOOKUP_BUF_SIZE]; + char *buf; KeySym keysym = NoSymbol; Status status; int mblen; jstring javastr; XIC ic;
*** 465,527 **** /* printf("lookupString: entering...\n"); */ - if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) { - currentX11InputMethodInstance = NULL; - return False; - } - pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance); if (pX11IMData == NULL) { - #if defined(__linux__) || defined(MACOSX) return False; - #else - return result; - #endif } if ((ic = pX11IMData->current_ic) == (XIC)0){ - #if defined(__linux__) || defined(MACOSX) return False; - #else - return result; - #endif - } - - /* allocate the lookup buffer at the first invocation */ - if (pX11IMData->lookup_buf_len == 0) { - pX11IMData->lookup_buf = (char *)malloc(INITIAL_LOOKUP_BUF_SIZE); - if (pX11IMData->lookup_buf == NULL) { - THROW_OUT_OF_MEMORY_ERROR(); - return result; - } - pX11IMData->lookup_buf_len = INITIAL_LOOKUP_BUF_SIZE; } ! mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf, ! pX11IMData->lookup_buf_len - 1, &keysym, &status); /* * In case of overflow, a buffer is allocated and it retries * XmbLookupString(). */ if (status == XBufferOverflow) { ! free((void *)pX11IMData->lookup_buf); ! pX11IMData->lookup_buf_len = 0; ! pX11IMData->lookup_buf = (char *)malloc(mblen + 1); ! if (pX11IMData->lookup_buf == NULL) { THROW_OUT_OF_MEMORY_ERROR(); return result; } ! pX11IMData->lookup_buf_len = mblen + 1; ! mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf, ! pX11IMData->lookup_buf_len - 1, &keysym, &status); } ! pX11IMData->lookup_buf[mblen] = 0; /* Get keysym without taking modifiers into account first to map * to AWT keyCode table. */ switch (status) { --- 392,429 ---- /* printf("lookupString: entering...\n"); */ pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance); if (pX11IMData == NULL) { return False; } if ((ic = pX11IMData->current_ic) == (XIC)0){ return False; } ! buf = mbbuf; ! mblen = XmbLookupString(ic, event, buf, ! buf_len - 1, &keysym, &status); /* * In case of overflow, a buffer is allocated and it retries * XmbLookupString(). */ if (status == XBufferOverflow) { ! buf_len = mblen + 1; ! buf = (char *)malloc(buf_len); ! if (buf == NULL) { THROW_OUT_OF_MEMORY_ERROR(); return result; } ! mblen = XmbLookupString(ic, event, buf, buf_len, &keysym, &status); } ! buf[mblen] = 0; /* Get keysym without taking modifiers into account first to map * to AWT keyCode table. */ switch (status) {
*** 534,585 **** } } composing = False; /*FALLTHRU*/ case XLookupChars: ! /* ! printf("lookupString: status=XLookupChars, type=%d, state=%x, keycode=%x, keysym=%x\n", ! event->type, event->state, event->keycode, keysym); ! */ ! javastr = JNU_NewStringPlatform(env, (const char *)pX11IMData->lookup_buf); if (javastr != NULL) { JNU_CallMethodByName(env, NULL, currentX11InputMethodInstance, "dispatchCommittedText", "(Ljava/lang/String;J)V", javastr, event->time); } break; case XLookupKeySym: ! /* ! printf("lookupString: status=XLookupKeySym, type=%d, state=%x, keycode=%x, keysym=%x\n", ! event->type, event->state, event->keycode, keysym); ! */ if (keysym == XK_Multi_key) composing = True; if (! composing) { *keysymp = keysym; result = False; } break; case XLookupNone: ! /* ! printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n", ! event->type, event->state, event->keycode, keysym); ! */ break; } return result; } ! #if defined(__linux__) || defined(MACOSX) ! static StatusWindow *createStatusWindow( ! Window parent) { StatusWindow *statusWindow; XSetWindowAttributes attrib; unsigned long attribmask; Window containerWindow; Window status; --- 436,492 ---- } } composing = False; /*FALLTHRU*/ case XLookupChars: ! /* ! printf("lookupString: status=XLookupChars, type=%d, state=%x, keycode=%x, keysym=%x\n", ! event->type, event->state, event->keycode, keysym); ! */ ! javastr = JNU_NewStringPlatform(env, (const char *)buf); if (javastr != NULL) { JNU_CallMethodByName(env, NULL, currentX11InputMethodInstance, "dispatchCommittedText", "(Ljava/lang/String;J)V", javastr, event->time); + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } } break; case XLookupKeySym: ! /* ! printf("lookupString: status=XLookupKeySym, type=%d, state=%x, keycode=%x, keysym=%x\n", ! event->type, event->state, event->keycode, keysym); ! */ if (keysym == XK_Multi_key) composing = True; if (! composing) { *keysymp = keysym; result = False; } break; case XLookupNone: ! /* ! printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n", ! event->type, event->state, event->keycode, keysym); ! */ break; } + if (buf != mbbuf) { + free(buf); + } return result; } ! static StatusWindow *createStatusWindow(Window parent) { StatusWindow *statusWindow; XSetWindowAttributes attrib; unsigned long attribmask; Window containerWindow; Window status;
*** 598,611 **** int screen = 0; int i; AwtGraphicsConfigDataPtr adata; extern int awt_numScreens; /*hardcode the size right now, should get the size base on font*/ ! int width=80, height=22; Window rootWindow; Window *ignoreWindowPtr; unsigned int ignoreUnit; XGetGeometry(dpy, parent, &rootWindow, &x, &y, &w, &h, &bw, &depth); attrib.override_redirect = True; attribmask = CWOverrideRedirect; --- 505,526 ---- int screen = 0; int i; AwtGraphicsConfigDataPtr adata; extern int awt_numScreens; /*hardcode the size right now, should get the size base on font*/ ! int width=80, height=22; Window rootWindow; Window *ignoreWindowPtr; unsigned int ignoreUnit; + Window grandParent; + Window target; + XFontSet fontset; + + fontset = create_fontset(); + if (NULL == fontset) { + return NULL; + } XGetGeometry(dpy, parent, &rootWindow, &x, &y, &w, &h, &bw, &depth); attrib.override_redirect = True; attribmask = CWOverrideRedirect;
*** 619,666 **** bg = adata->AwtColorMatch(255, 255, 255, adata); fg = adata->AwtColorMatch(0, 0, 0, adata); light = adata->AwtColorMatch(195, 195, 195, adata); dim = adata->AwtColorMatch(128, 128, 128, adata); ! XGetWindowAttributes(dpy, parent, &xwa); bw = 2; /*xwa.border_width does not have the correct value*/ /*compare the size difference between parent container and shell widget, the diff should be the border frame and title bar height (?)*/ XQueryTree( dpy, ! parent, &rootWindow, &containerWindow, &ignoreWindowPtr, &ignoreUnit); XGetWindowAttributes(dpy, containerWindow, &xxwa); ! off_x = (xxwa.width - xwa.width) / 2; ! off_y = xxwa.height - xwa.height - off_x; /*it's magic:-) */ /*get the size of root window*/ XGetWindowAttributes(dpy, rootWindow, &xxwa); XTranslateCoordinates(dpy, ! parent, xwa.root, xwa.x, xwa.y, &x, &y, &child); xx = x - off_x; yy = y + xwa.height - off_y; if (xx < 0 ){ xx = 0; } ! if (xx + width > xxwa.width){ xx = xxwa.width - width; } ! if (yy + height > xxwa.height){ yy = xxwa.height - height; } status = XCreateWindow(dpy, xwa.root, xx, yy, width, height, 0, --- 534,610 ---- bg = adata->AwtColorMatch(255, 255, 255, adata); fg = adata->AwtColorMatch(0, 0, 0, adata); light = adata->AwtColorMatch(195, 195, 195, adata); dim = adata->AwtColorMatch(128, 128, 128, adata); ! grandParent = getGrandParent(parent); ! target = (grandParent == 0) ? parent : grandParent; ! XGetWindowAttributes(dpy, target, &xwa); bw = 2; /*xwa.border_width does not have the correct value*/ /*compare the size difference between parent container and shell widget, the diff should be the border frame and title bar height (?)*/ XQueryTree( dpy, ! target, &rootWindow, &containerWindow, &ignoreWindowPtr, &ignoreUnit); XGetWindowAttributes(dpy, containerWindow, &xxwa); ! XTranslateCoordinates(dpy, ! target, xwa.root, ! 0, 0, ! &x, &y, &child); ! ! if (containerWindow == rootWindow) { ! off_x = 0; off_y = STATUS_MARGIN; ! } else { ! XGetWindowAttributes(dpy, containerWindow, &xxwa); ! off_x = (xxwa.width - xwa.width) / 2; ! /* off_y = xxwa.height - xwa.height - off_x;*/ /*it's magic:-) */ ! { ! int cx, cy; ! XTranslateCoordinates(dpy, ! containerWindow, xxwa.root, ! 0, 0, ! &cx, &cy, ! &child); ! off_y = (xxwa.height + cy) - (xwa.height + y); ! } ! } /*get the size of root window*/ XGetWindowAttributes(dpy, rootWindow, &xxwa); XTranslateCoordinates(dpy, ! target, xwa.root, xwa.x, xwa.y, &x, &y, &child); xx = x - off_x; yy = y + xwa.height - off_y; if (xx < 0 ){ xx = 0; } ! if (xx + width > xxwa.width) { xx = xxwa.width - width; } ! if (yy + height > xxwa.height) { yy = xxwa.height - height; } + if ((DefaultVisual(dpy,screen))->class != adata->awt_visInfo.visual->class && + adata->awt_visInfo.visual->class == TrueColor) { + attrib.colormap = XCreateColormap(dpy, xwa.root, + adata->awt_visInfo.visual, AllocNone ); + attrib.border_pixel = BlackPixel(dpy, screen) ; + attribmask |= CWColormap | CWBorderPixel; + } + status = XCreateWindow(dpy, xwa.root, xx, yy, width, height, 0,
*** 669,713 **** adata->awt_visInfo.visual, attribmask, &attrib); XSelectInput(dpy, status, ExposureMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask | VisibilityChangeMask); statusWindow = (StatusWindow*) calloc(1, sizeof(StatusWindow)); if (statusWindow == NULL){ THROW_OUT_OF_MEMORY_ERROR(); return NULL; } statusWindow->w = status; ! //12-point font ! statusWindow->fontset = XCreateFontSet(dpy, ! "-*-*-medium-r-normal-*-*-120-*-*-*-*", ! &mclr, &mccr, &dsr); ! /* In case we didn't find the font set, release the list of missing characters */ ! if (mccr > 0) { ! XFreeStringList(mclr); ! } statusWindow->parent = parent; statusWindow->on = False; statusWindow->x = x; statusWindow->y = y; statusWindow->width = xwa.width; statusWindow->height = xwa.height; statusWindow->off_x = off_x; statusWindow->off_y = off_y; statusWindow->bWidth = bw; statusWindow->statusH = height; statusWindow->statusW = width; statusWindow->rootH = xxwa.height; statusWindow->rootW = xxwa.width; statusWindow->lightGC = XCreateGC(dpy, status, valuemask, &values); XSetForeground(dpy, statusWindow->lightGC, light); statusWindow->dimGC = XCreateGC(dpy, status, valuemask, &values); XSetForeground(dpy, statusWindow->dimGC, dim); ! statusWindow->fgGC = XCreateGC(dpy, status, valuemask, &values); XSetForeground(dpy, statusWindow->fgGC, fg); ! statusWindow->bgGC = XCreateGC(dpy, status, valuemask, &values); XSetForeground(dpy, statusWindow->bgGC, bg); return statusWindow; } /* This method is to turn off or turn on the status window. */ static void onoffStatusWindow(X11InputMethodData* pX11IMData, --- 613,662 ---- adata->awt_visInfo.visual, attribmask, &attrib); XSelectInput(dpy, status, ExposureMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask | VisibilityChangeMask); + if (grandParent != 0){ + long mask; + XGetWindowAttributes(dpy, grandParent, &xwa); + mask = xwa.your_event_mask | StructureNotifyMask | + VisibilityChangeMask | PropertyChangeMask; + XSelectInput(dpy, grandParent,mask); + } + statusWindow = (StatusWindow*) calloc(1, sizeof(StatusWindow)); if (statusWindow == NULL){ THROW_OUT_OF_MEMORY_ERROR(); return NULL; } statusWindow->w = status; ! statusWindow->fontset = fontset; statusWindow->parent = parent; + statusWindow->grandParent = grandParent; statusWindow->on = False; statusWindow->x = x; statusWindow->y = y; statusWindow->width = xwa.width; statusWindow->height = xwa.height; statusWindow->off_x = off_x; statusWindow->off_y = off_y; statusWindow->bWidth = bw; statusWindow->statusH = height; statusWindow->statusW = width; + statusWindow->peTextW = 0; statusWindow->rootH = xxwa.height; statusWindow->rootW = xxwa.width; statusWindow->lightGC = XCreateGC(dpy, status, valuemask, &values); XSetForeground(dpy, statusWindow->lightGC, light); statusWindow->dimGC = XCreateGC(dpy, status, valuemask, &values); XSetForeground(dpy, statusWindow->dimGC, dim); ! statusWindow->fgGC = create_gc(status, FALSE); XSetForeground(dpy, statusWindow->fgGC, fg); ! statusWindow->bgGC = create_gc(status, TRUE); XSetForeground(dpy, statusWindow->bgGC, bg); + statusWindow->status_ready = False; + wcscpy(statusWindow->status, L""); return statusWindow; } /* This method is to turn off or turn on the status window. */ static void onoffStatusWindow(X11InputMethodData* pX11IMData,
*** 716,769 **** XWindowAttributes xwa; Window child; int x, y; StatusWindow *statusWindow = NULL; ! if (NULL == currentX11InputMethodInstance || ! NULL == pX11IMData || NULL == (statusWindow = pX11IMData->statusWindow)){ return; } ! if (ON == False){ XUnmapWindow(dpy, statusWindow->w); - statusWindow->on = False; return; } ! parent = JNU_CallMethodByName(GetJNIEnv(), NULL, pX11IMData->x11inputmethod, ! "getCurrentParentWindow", ! "()J").j; ! if (statusWindow->parent != parent){ ! statusWindow->parent = parent; } ! XGetWindowAttributes(dpy, parent, &xwa); ! XTranslateCoordinates(dpy, ! parent, xwa.root, ! xwa.x, xwa.y, ! &x, &y, ! &child); ! if (statusWindow->x != x ! || statusWindow->y != y ! || statusWindow->height != xwa.height){ ! statusWindow->x = x; ! statusWindow->y = y; ! statusWindow->height = xwa.height; ! x = statusWindow->x - statusWindow->off_x; ! y = statusWindow->y + statusWindow->height - statusWindow->off_y; ! if (x < 0 ){ ! x = 0; ! } ! if (x + statusWindow->statusW > statusWindow->rootW){ ! x = statusWindow->rootW - statusWindow->statusW; ! } ! if (y + statusWindow->statusH > statusWindow->rootH){ ! y = statusWindow->rootH - statusWindow->statusH; } - XMoveWindow(dpy, statusWindow->w, x, y); } ! statusWindow->on = True; ! XMapWindow(dpy, statusWindow->w); } void paintStatusWindow(StatusWindow *statusWindow){ Window win = statusWindow->w; GC lightgc = statusWindow->lightGC; --- 665,704 ---- XWindowAttributes xwa; Window child; int x, y; StatusWindow *statusWindow = NULL; ! if (NULL == pX11IMData || NULL == (statusWindow = pX11IMData->statusWindow)){ return; } ! if (ON == False) { XUnmapWindow(dpy, statusWindow->w); return; } ! if (NULL == currentX11InputMethodInstance){ ! return; } ! { ! JNIEnv *env = GetJNIEnv(); ! parent = JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod, ! "getCurrentParentWindow", ! "()J").j; ! if ((*env)->ExceptionOccurred(env)) { ! (*env)->ExceptionDescribe(env); ! (*env)->ExceptionClear(env); } } ! if (statusWindow->parent != parent) { ! statusWindow->parent = parent; ! } ! if (st_wcslen(statusWindow->status) > 0 || ! (statusWindow->peText != NULL && st_wcslen(statusWindow->peText) > 0 )) { ! moveStatusWindow(statusWindow); ! XMapRaised(dpy, statusWindow->w); ! } } void paintStatusWindow(StatusWindow *statusWindow){ Window win = statusWindow->w; GC lightgc = statusWindow->lightGC;
*** 772,896 **** GC fggc = statusWindow->fgGC; int width = statusWindow->statusW; int height = statusWindow->statusH; int bwidth = statusWindow->bWidth; ! XFillRectangle(dpy, win, bggc, 0, 0, width, height); ! /* draw border */ ! XDrawLine(dpy, win, fggc, 0, 0, width, 0); ! XDrawLine(dpy, win, fggc, 0, height-1, width-1, height-1); ! XDrawLine(dpy, win, fggc, 0, 0, 0, height-1); ! XDrawLine(dpy, win, fggc, width-1, 0, width-1, height-1); ! ! XDrawLine(dpy, win, lightgc, 1, 1, width-bwidth, 1); ! XDrawLine(dpy, win, lightgc, 1, 1, 1, height-2); ! XDrawLine(dpy, win, lightgc, 1, height-2, width-bwidth, height-2); ! XDrawLine(dpy, win, lightgc, width-bwidth-1, 1, width-bwidth-1, height-2); ! ! XDrawLine(dpy, win, dimgc, 2, 2, 2, height-3); ! XDrawLine(dpy, win, dimgc, 2, height-3, width-bwidth-1, height-3); ! XDrawLine(dpy, win, dimgc, 2, 2, width-bwidth-2, 2); ! XDrawLine(dpy, win, dimgc, width-bwidth, 2, width-bwidth, height-3); ! if (statusWindow->fontset){ ! XmbDrawString(dpy, win, statusWindow->fontset, fggc, ! bwidth + 2, height - bwidth - 4, ! statusWindow->status, ! strlen(statusWindow->status)); } ! else{ /*too bad we failed to create a fontset for this locale*/ XDrawString(dpy, win, fggc, bwidth + 2, height - bwidth - 4, "[InputMethod ON]", strlen("[InputMethod ON]")); } } ! void statusWindowEventHandler(XEvent event){ JNIEnv *env = GetJNIEnv(); X11InputMethodData *pX11IMData = NULL; StatusWindow *statusWindow; ! if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) { ! currentX11InputMethodInstance = NULL; ! return; ! } ! ! if (NULL == currentX11InputMethodInstance ! || NULL == (pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance)) ! || NULL == (statusWindow = pX11IMData->statusWindow) ! || statusWindow->w != event.xany.window){ ! return; } ! switch (event.type){ ! case Expose: ! paintStatusWindow(statusWindow); ! break; ! case MapNotify: ! case ConfigureNotify: ! { ! /*need to reset the stackMode...*/ ! XWindowChanges xwc; ! int value_make = CWStackMode; ! xwc.stack_mode = TopIf; ! XConfigureWindow(dpy, statusWindow->w, value_make, &xwc); ! } ! break; /* ! case UnmapNotify: ! case VisibilityNotify: ! break; */ ! default: ! break; ! } } ! static void adjustStatusWindow(Window shell){ JNIEnv *env = GetJNIEnv(); X11InputMethodData *pX11IMData = NULL; StatusWindow *statusWindow; if (NULL == currentX11InputMethodInstance - || !isX11InputMethodGRefInList(currentX11InputMethodInstance) || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance)) || NULL == (statusWindow = pX11IMData->statusWindow) ! || !statusWindow->on) { ! return; ! } { ! XWindowAttributes xwa; ! int x, y; ! Window child; ! XGetWindowAttributes(dpy, shell, &xwa); ! XTranslateCoordinates(dpy, ! shell, xwa.root, ! xwa.x, xwa.y, ! &x, &y, ! &child); ! if (statusWindow->x != x ! || statusWindow->y != y ! || statusWindow->height != xwa.height){ ! statusWindow->x = x; ! statusWindow->y = y; ! statusWindow->height = xwa.height; ! ! x = statusWindow->x - statusWindow->off_x; ! y = statusWindow->y + statusWindow->height - statusWindow->off_y; ! if (x < 0 ){ ! x = 0; ! } ! if (x + statusWindow->statusW > statusWindow->rootW){ ! x = statusWindow->rootW - statusWindow->statusW; ! } ! if (y + statusWindow->statusH > statusWindow->rootH){ ! y = statusWindow->rootH - statusWindow->statusH; ! } ! XMoveWindow(dpy, statusWindow->w, x, y); ! } } } ! #endif /* __linux__ || MACOSX */ /* * Creates two XICs, one for active clients and the other for passive * clients. All information on those XICs are stored in the * X11InputMethodData given by the pX11IMData parameter. * --- 707,828 ---- GC fggc = statusWindow->fgGC; int width = statusWindow->statusW; int height = statusWindow->statusH; int bwidth = statusWindow->bWidth; ! int len; ! XRectangle logical, ink; ! ! if (NULL == statusWindow) return; ! if ((len = st_wcslen(statusWindow->status)) == 0) { ! return; } ! XwcTextExtents(statusWindow->fontset, statusWindow->status, ! len, &ink, &logical); ! width = logical.width; ! height = logical.height; ! ! XFillRectangle(dpy, win, bggc, 0, 0, width+2, height+2); ! ! XDrawLine(dpy, win, fggc, 0, 0, width+2, 0); ! XDrawLine(dpy, win, fggc, 0, height+2, width+2, height+2); ! XDrawLine(dpy, win, fggc, 0, 0, 0, height+2); ! XDrawLine(dpy, win, fggc, width+2, 0, width+2, height+2); ! ! if (statusWindow->fontset) { ! XwcDrawString(dpy, win, statusWindow->fontset, fggc, ! -logical.x + 1, -logical.y + 1, ! statusWindow->status, ! st_wcslen(statusWindow->status)); ! } else { /*too bad we failed to create a fontset for this locale*/ XDrawString(dpy, win, fggc, bwidth + 2, height - bwidth - 4, "[InputMethod ON]", strlen("[InputMethod ON]")); } } ! Bool statusWindowEventHandler(XEvent event) { JNIEnv *env = GetJNIEnv(); X11InputMethodData *pX11IMData = NULL; StatusWindow *statusWindow; ! if (NULL == currentX11InputMethodInstance || ! NULL == (pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance)) || ! NULL == (statusWindow = pX11IMData->statusWindow)) ! { ! return False; } ! if (statusWindow->w == event.xany.window) { ! switch (event.type) { ! case Expose: ! paintStatusWindow(statusWindow); ! if (statusWindow->peText) ! draw_preedit(statusWindow); ! arrange_window_stack(statusWindow); ! break; ! case ConfigureNotify: ! case VisibilityNotify: ! arrange_window_stack(statusWindow); ! break; /* ! case UnmapNotify: ! case VisibilityNotify: ! break; */ ! default: ! break; ! } ! return True; ! } else if ((statusWindow->parent == event.xany.window) || ! (statusWindow->grandParent && statusWindow->grandParent == event.xany.window)) { ! switch (event.type) { ! case MapNotify: ! if (statusWindow->on) { ! onoffStatusWindow(pX11IMData, statusWindow->parent, True); ! } ! break; ! case UnmapNotify: ! onoffStatusWindow(pX11IMData, 0, False); ! break; ! case VisibilityNotify: ! if (statusWindow->on) { ! arrange_window_stack(statusWindow); ! } ! break; ! case ConfigureNotify: ! if (statusWindow->grandParent && statusWindow->on) { ! moveStatusWindow(statusWindow); ! } ! case PropertyNotify: ! if (statusWindow->on) { ! arrange_window_stack(statusWindow); ! } ! break; ! default: ! break; ! } ! } ! return False; } ! static void adjustStatusWindow(Window shell) { JNIEnv *env = GetJNIEnv(); X11InputMethodData *pX11IMData = NULL; StatusWindow *statusWindow; if (NULL == currentX11InputMethodInstance || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance)) || NULL == (statusWindow = pX11IMData->statusWindow) ! || !statusWindow->on) { ! return; } + + moveStatusWindow(statusWindow); } ! /* * Creates two XICs, one for active clients and the other for passive * clients. All information on those XICs are stored in the * X11InputMethodData given by the pX11IMData parameter. *
*** 907,939 **** createXIC(JNIEnv * env, X11InputMethodData *pX11IMData, Window w) { XVaNestedList preedit = NULL; XVaNestedList status = NULL; XIMStyle on_the_spot_styles = XIMPreeditCallbacks, active_styles = 0, passive_styles = 0, no_styles = 0; XIMCallback *callbacks; unsigned short i; XIMStyles *im_styles; char *ret = NULL; if (X11im == NULL) { return False; } if (!w) { return False; } ret = XGetIMValues(X11im, XNQueryInputStyle, &im_styles, NULL); if (ret != NULL) { jio_fprintf(stderr,"XGetIMValues: %s\n",ret); return FALSE ; } - #if defined(__linux__) || defined(MACOSX) on_the_spot_styles |= XIMStatusNothing; /*kinput does not support XIMPreeditCallbacks and XIMStatusArea at the same time, so use StatusCallback to draw the status ourself --- 839,881 ---- createXIC(JNIEnv * env, X11InputMethodData *pX11IMData, Window w) { XVaNestedList preedit = NULL; XVaNestedList status = NULL; XIMStyle on_the_spot_styles = XIMPreeditCallbacks, + in_place_styles = 0, active_styles = 0, passive_styles = 0, no_styles = 0; XIMCallback *callbacks; unsigned short i; XIMStyles *im_styles; char *ret = NULL; + Bool passiveStatusWindow = False; + pX11IMData->statusWindow = NULL; if (X11im == NULL) { return False; } if (!w) { return False; } + if (getenv("IBMJAVA_PASSIVE") == NULL) { + passiveStatusWindow = False; + } else { + passiveStatusWindow = True; + } + + if (isNativeIm()) { passiveStatusWindow = True; } + ret = XGetIMValues(X11im, XNQueryInputStyle, &im_styles, NULL); if (ret != NULL) { jio_fprintf(stderr,"XGetIMValues: %s\n",ret); return FALSE ; } on_the_spot_styles |= XIMStatusNothing; /*kinput does not support XIMPreeditCallbacks and XIMStatusArea at the same time, so use StatusCallback to draw the status ourself
*** 942,988 **** if (im_styles->supported_styles[i] == (XIMPreeditCallbacks | XIMStatusCallbacks)) { on_the_spot_styles = (XIMPreeditCallbacks | XIMStatusCallbacks); break; } } - #else /*! __linux__ && !MACOSX */ - on_the_spot_styles |= XIMStatusNothing; - #endif /* __linux__ || MACOSX */ for (i = 0; i < im_styles->count_styles; i++) { ! active_styles |= im_styles->supported_styles[i] & on_the_spot_styles; ! passive_styles |= im_styles->supported_styles[i] & ROOT_WINDOW_STYLES; ! no_styles |= im_styles->supported_styles[i] & NO_STYLES; } XFree(im_styles); if (active_styles != on_the_spot_styles) { if (passive_styles == ROOT_WINDOW_STYLES) active_styles = passive_styles; else { if (no_styles == NO_STYLES) active_styles = passive_styles = NO_STYLES; else active_styles = passive_styles = 0; } } else { if (passive_styles != ROOT_WINDOW_STYLES) { if (no_styles == NO_STYLES) active_styles = passive_styles = NO_STYLES; else active_styles = passive_styles = 0; } } if (active_styles == on_the_spot_styles) { - pX11IMData->ic_passive = XCreateIC(X11im, - XNClientWindow, w, - XNFocusWindow, w, - XNInputStyle, passive_styles, - NULL); - callbacks = (XIMCallback *)malloc(sizeof(XIMCallback) * NCALLBACKS); if (callbacks == (XIMCallback *)NULL) return False; pX11IMData->callbacks = callbacks; --- 884,935 ---- if (im_styles->supported_styles[i] == (XIMPreeditCallbacks | XIMStatusCallbacks)) { on_the_spot_styles = (XIMPreeditCallbacks | XIMStatusCallbacks); break; } } for (i = 0; i < im_styles->count_styles; i++) { ! if (im_styles->supported_styles[i] == on_the_spot_styles) ! active_styles = im_styles->supported_styles[i]; ! if (im_styles->supported_styles[i] == ROOT_WINDOW_STYLES) ! passive_styles = im_styles->supported_styles[i]; ! if (im_styles->supported_styles[i] == IN_PLACE_STYLES) { ! in_place_styles = im_styles->supported_styles[i]; ! } ! if (im_styles->supported_styles[i] == NO_STYLES) { ! no_styles = im_styles->supported_styles[i]; ! } } XFree(im_styles); if (active_styles != on_the_spot_styles) { if (passive_styles == ROOT_WINDOW_STYLES) active_styles = passive_styles; else { + if (in_place_styles == IN_PLACE_STYLES){ + active_styles = passive_styles = IN_PLACE_STYLES; + } else { if (no_styles == NO_STYLES) active_styles = passive_styles = NO_STYLES; else active_styles = passive_styles = 0; + } } } else { + if (!passiveStatusWindow) { if (passive_styles != ROOT_WINDOW_STYLES) { if (no_styles == NO_STYLES) active_styles = passive_styles = NO_STYLES; else active_styles = passive_styles = 0; } + } else + passive_styles = active_styles; } if (active_styles == on_the_spot_styles) { callbacks = (XIMCallback *)malloc(sizeof(XIMCallback) * NCALLBACKS); if (callbacks == (XIMCallback *)NULL) return False; pX11IMData->callbacks = callbacks;
*** 998,1090 **** XNPreeditDrawCallback, &callbacks[PreeditDrawIndex], XNPreeditCaretCallback, &callbacks[PreeditCaretIndex], NULL); if (preedit == (XVaNestedList)NULL) goto err; - #if defined(__linux__) || defined(MACOSX) /*always try XIMStatusCallbacks for active client...*/ { status = (XVaNestedList)XVaCreateNestedList(0, XNStatusStartCallback, &callbacks[StatusStartIndex], XNStatusDoneCallback, &callbacks[StatusDoneIndex], XNStatusDrawCallback, &callbacks[StatusDrawIndex], NULL); if (status == NULL) goto err; pX11IMData->statusWindow = createStatusWindow(w); pX11IMData->ic_active = XCreateIC(X11im, XNClientWindow, w, XNFocusWindow, w, XNInputStyle, active_styles, XNPreeditAttributes, preedit, XNStatusAttributes, status, NULL); XFree((void *)status); XFree((void *)preedit); } ! #else /* !__linux__ && !MACOSX */ ! pX11IMData->ic_active = XCreateIC(X11im, ! XNClientWindow, w, ! XNFocusWindow, w, ! XNInputStyle, active_styles, ! XNPreeditAttributes, preedit, ! NULL); ! XFree((void *)preedit); ! #endif /* __linux__ || MACOSX */ } else { pX11IMData->ic_active = XCreateIC(X11im, XNClientWindow, w, XNFocusWindow, w, XNInputStyle, active_styles, NULL); pX11IMData->ic_passive = pX11IMData->ic_active; } if (pX11IMData->ic_active == (XIC)0 || pX11IMData->ic_passive == (XIC)0) { return False; } ! /* ! * Use commit string call back if possible. ! * This will ensure the correct order of preedit text and commit text ! */ ! { ! XIMCallback cb; ! cb.client_data = (XPointer) pX11IMData->x11inputmethod; ! cb.callback = (XIMProc) CommitStringCallback; ! XSetICValues (pX11IMData->ic_active, XNCommitStringCallback, &cb, NULL); ! if (pX11IMData->ic_active != pX11IMData->ic_passive) { ! XSetICValues (pX11IMData->ic_passive, XNCommitStringCallback, &cb, NULL); ! } ! } ! ! /* Add the global reference object to X11InputMethod to the list. */ ! addToX11InputMethodGRefList(pX11IMData->x11inputmethod); return True; err: if (preedit) XFree((void *)preedit); THROW_OUT_OF_MEMORY_ERROR(); return False; } ! static void PreeditStartCallback(XIC ic, XPointer client_data, XPointer call_data) { ! /*ARGSUSED*/ ! /* printf("Native: PreeditCaretCallback\n"); */ } static void PreeditDoneCallback(XIC ic, XPointer client_data, XPointer call_data) { ! /*ARGSUSED*/ ! /* printf("Native: StatusStartCallback\n"); */ } /* * Translate the preedit draw callback items to Java values and invoke * X11InputMethod.dispatchComposedText(). --- 945,1071 ---- XNPreeditDrawCallback, &callbacks[PreeditDrawIndex], XNPreeditCaretCallback, &callbacks[PreeditCaretIndex], NULL); if (preedit == (XVaNestedList)NULL) goto err; /*always try XIMStatusCallbacks for active client...*/ { + if (on_the_spot_styles & XIMStatusCallbacks) { status = (XVaNestedList)XVaCreateNestedList(0, XNStatusStartCallback, &callbacks[StatusStartIndex], XNStatusDoneCallback, &callbacks[StatusDoneIndex], XNStatusDrawCallback, &callbacks[StatusDrawIndex], NULL); if (status == NULL) goto err; + } pX11IMData->statusWindow = createStatusWindow(w); pX11IMData->ic_active = XCreateIC(X11im, XNClientWindow, w, XNFocusWindow, w, XNInputStyle, active_styles, XNPreeditAttributes, preedit, XNStatusAttributes, status, NULL); + if (NULL != pX11IMData->statusWindow) { + pX11IMData->statusWindow->status_ready = True; + } XFree((void *)status); XFree((void *)preedit); } ! if (passiveStatusWindow) { ! pX11IMData->ic_passive = pX11IMData->ic_active; ! } else { ! pX11IMData->ic_passive = XCreateIC(X11im, ! XNClientWindow, w, ! XNFocusWindow, w, ! XNInputStyle, passive_styles, ! NULL); ! } } else { pX11IMData->ic_active = XCreateIC(X11im, XNClientWindow, w, XNFocusWindow, w, XNInputStyle, active_styles, NULL); pX11IMData->ic_passive = pX11IMData->ic_active; } + // The code set the IC mode that the preedit state is not initialied + // at XmbResetIC. This attribute can be set at XCreateIC. I separately + // set the attribute to avoid the failure of XCreateIC at some platform + // which does not support the attribute. + if (pX11IMData->ic_active != 0) + XSetICValues(pX11IMData->ic_active, + XNResetState, XIMPreserveState, NULL); + if (pX11IMData->ic_passive != 0 && + pX11IMData->ic_active != pX11IMData->ic_passive) + XSetICValues(pX11IMData->ic_passive, + XNResetState, XIMInitialState, NULL); + + pX11IMData->passiveStatusWindow = passiveStatusWindow; + if (pX11IMData->ic_active == (XIC)0 || pX11IMData->ic_passive == (XIC)0) { return False; } ! /* Unset focus to avoid unexpected IM on */ ! setXICFocus(pX11IMData->ic_active, False); ! if (pX11IMData->ic_active != pX11IMData->ic_passive) ! setXICFocus(pX11IMData->ic_passive, False); return True; err: if (preedit) XFree((void *)preedit); THROW_OUT_OF_MEMORY_ERROR(); return False; } ! static int PreeditStartCallback(XIC ic, XPointer client_data, XPointer call_data) { ! JNIEnv *env = GetJNIEnv(); ! X11InputMethodData *pX11IMData; ! ! pX11IMData = getX11InputMethodData(env, (jobject)client_data); ! if (pX11IMData == NULL || pX11IMData->statusWindow == NULL) { ! return 0; ! } ! resetPassivePreeditText(pX11IMData->statusWindow); ! ! return -1; /* unlimited length for preedit text */ } static void PreeditDoneCallback(XIC ic, XPointer client_data, XPointer call_data) { ! JNIEnv *env = GetJNIEnv(); ! X11InputMethodData *pX11IMData; ! ! pX11IMData = getX11InputMethodData(env, (jobject)client_data); ! if (pX11IMData == NULL) { ! return; ! } ! ! if (!pX11IMData->isActiveClient) { ! resetPassivePreeditText(pX11IMData->statusWindow); ! shrink_status(pX11IMData->statusWindow); ! } ! else{ ! JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod, ! "clearComposedText", ! "(J)V", ! awt_util_nowMillisUTC()); ! if ((*env)->ExceptionOccurred(env)) { ! (*env)->ExceptionDescribe(env); ! (*env)->ExceptionClear(env); ! } ! } } /* * Translate the preedit draw callback items to Java values and invoke * X11InputMethod.dispatchComposedText().
*** 1106,1141 **** /* printf("Native: PreeditDrawCallback() \n"); */ if (pre_draw == NULL) { return; } AWT_LOCK(); ! if (!isX11InputMethodGRefInList((jobject)client_data)) { ! if ((jobject)client_data == currentX11InputMethodInstance) { ! currentX11InputMethodInstance = NULL; ! } goto finally; } ! if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) { goto finally; } if ((text = pre_draw->text) != NULL) { ! if (text->string.multi_byte != NULL) { ! if (pre_draw->text->encoding_is_wchar == False) { ! javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte); ! if (javastr == NULL) { ! goto finally; ! } ! } else { ! char *mbstr = wcstombsdmp(text->string.wide_char, text->length); ! if (mbstr == NULL) { ! goto finally; ! } ! javastr = JNU_NewStringPlatform(env, (const char *)mbstr); ! free(mbstr); ! if (javastr == NULL) { ! goto finally; } } } if (text->feedback != NULL) { int cnt; --- 1087,1125 ---- /* printf("Native: PreeditDrawCallback() \n"); */ if (pre_draw == NULL) { return; } AWT_LOCK(); ! if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) { goto finally; } ! ! if (!pX11IMData->isActiveClient){ ! if (ic == pX11IMData->ic_passive) { ! preedit_draw_passive(pX11IMData, pre_draw); ! } goto finally; } if ((text = pre_draw->text) != NULL) { ! if (is_text_available(text)) { ! if (text->string.multi_byte != NULL) { ! if (pre_draw->text->encoding_is_wchar == False) { ! javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte); ! if (javastr == NULL) { ! goto finally; ! } ! } else { ! char *mbstr = wcstombsdmp(text->string.wide_char, text->length); ! if (mbstr == NULL) { ! goto finally; ! } ! javastr = JNU_NewStringPlatform(env, (const char *)mbstr); ! free(mbstr); ! if (javastr == NULL) { ! goto finally; ! } } } } if (text->feedback != NULL) { int cnt;
*** 1174,1384 **** style, (jint)pre_draw->chg_first, (jint)pre_draw->chg_length, (jint)pre_draw->caret, awt_util_nowMillisUTC()); finally: AWT_UNLOCK(); return; } static void PreeditCaretCallback(XIC ic, XPointer client_data, XIMPreeditCaretCallbackStruct *pre_caret) { ! /*ARGSUSED*/ ! /* printf("Native: PreeditCaretCallback\n"); */ } - #if defined(__linux__) || defined(MACOSX) static void StatusStartCallback(XIC ic, XPointer client_data, XPointer call_data) { /*ARGSUSED*/ /*printf("StatusStartCallback:\n"); */ - } static void StatusDoneCallback(XIC ic, XPointer client_data, XPointer call_data) { /*ARGSUSED*/ /*printf("StatusDoneCallback:\n"); */ - } ! static void ! StatusDrawCallback(XIC ic, XPointer client_data, ! XIMStatusDrawCallbackStruct *status_draw) { /*ARGSUSED*/ /*printf("StatusDrawCallback:\n"); */ JNIEnv *env = GetJNIEnv(); X11InputMethodData *pX11IMData = NULL; StatusWindow *statusWindow; AWT_LOCK(); - if (!isX11InputMethodGRefInList((jobject)client_data)) { - if ((jobject)client_data == currentX11InputMethodInstance) { - currentX11InputMethodInstance = NULL; - } - goto finally; - } - if (NULL == (pX11IMData = getX11InputMethodData(env, (jobject)client_data)) || NULL == (statusWindow = pX11IMData->statusWindow)){ goto finally; } - currentX11InputMethodInstance = (jobject)client_data; ! if (status_draw->type == XIMTextType){ XIMText *text = (status_draw->data).text; ! if (text != NULL){ ! if (text->string.multi_byte != NULL) { ! strncpy(statusWindow->status, text->string.multi_byte, MAX_STATUS_LEN); ! statusWindow->status[MAX_STATUS_LEN - 1] = '\0'; ! } ! else { ! char *mbstr = wcstombsdmp(text->string.wide_char, text->length); ! strncpy(statusWindow->status, mbstr, MAX_STATUS_LEN); ! statusWindow->status[MAX_STATUS_LEN - 1] = '\0'; } ! statusWindow->on = True; ! onoffStatusWindow(pX11IMData, statusWindow->parent, True); ! paintStatusWindow(statusWindow); } else { ! statusWindow->on = False; /*just turnoff the status window paintStatusWindow(statusWindow); */ onoffStatusWindow(pX11IMData, 0, False); } } finally: AWT_UNLOCK(); } - #endif /* __linux__ || MACOSX */ ! static void CommitStringCallback(XIC ic, XPointer client_data, XPointer call_data) { ! JNIEnv *env = GetJNIEnv(); ! XIMText * text = (XIMText *)call_data; ! X11InputMethodData *pX11IMData = NULL; ! jstring javastr; ! AWT_LOCK(); ! if (!isX11InputMethodGRefInList((jobject)client_data)) { ! if ((jobject)client_data == currentX11InputMethodInstance) { ! currentX11InputMethodInstance = NULL; ! } ! goto finally; } ! if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) { ! goto finally; } ! currentX11InputMethodInstance = (jobject)client_data; ! if (text->encoding_is_wchar == False) { ! javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte); } else { ! char *mbstr = wcstombsdmp(text->string.wide_char, text->length); ! if (mbstr == NULL) { ! goto finally; } - javastr = JNU_NewStringPlatform(env, (const char *)mbstr); - free(mbstr); } ! if (javastr != NULL) { ! JNU_CallMethodByName(env, NULL, ! pX11IMData->x11inputmethod, ! "dispatchCommittedText", ! "(Ljava/lang/String;J)V", ! javastr, ! awt_util_nowMillisUTC()); } ! finally: ! AWT_UNLOCK(); } ! static void OpenXIMCallback(Display *display, XPointer client_data, XPointer call_data) { ! XIMCallback ximCallback; ! X11im = XOpenIM(display, NULL, NULL, NULL); ! if (X11im == NULL) { return; } ! ximCallback.callback = (XIMProc)DestroyXIMCallback; ! ximCallback.client_data = NULL; ! XSetIMValues(X11im, XNDestroyCallback, &ximCallback, NULL); } ! static void DestroyXIMCallback(XIM im, XPointer client_data, XPointer call_data) { ! /* mark that XIM server was destroyed */ ! X11im = NULL; ! JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); ! /* free the old pX11IMData and set it to null. this also avoids crashing ! * the jvm if the XIM server reappears */ ! X11InputMethodData *pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance); } ! /* ! * Class: sun_awt_X11InputMethod ! * Method: initIDs ! * Signature: ()V ! */ ! /* This function gets called from the static initializer for ! X11InputMethod.java ! to initialize the fieldIDs for fields that may be accessed from C */ ! JNIEXPORT void JNICALL ! Java_sun_awt_X11InputMethod_initIDs(JNIEnv *env, jclass cls) { ! x11InputMethodIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J"); } JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XInputMethod_openXIMNative(JNIEnv *env, ! jobject this, ! jlong display) { Bool registered; AWT_LOCK(); dpy = (Display *)jlong_to_ptr(display); ! /* Use IMInstantiate call back only on Linux, as there is a bug in Solaris ! (4768335) ! */ ! #if defined(__linux__) || defined(MACOSX) ! registered = XRegisterIMInstantiateCallback(dpy, NULL, NULL, ! NULL, (XIDProc)OpenXIMCallback, NULL); ! if (!registered) { ! /* directly call openXIM callback */ ! #endif ! OpenXIMCallback(dpy, NULL, NULL); ! #if defined(__linux__) || defined(MACOSX) } - #endif AWT_UNLOCK(); return JNI_TRUE; } JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XInputMethod_createXICNative(JNIEnv *env, ! jobject this, ! jlong window) { X11InputMethodData *pX11IMData; jobject globalRef; XIC ic; --- 1158,1922 ---- style, (jint)pre_draw->chg_first, (jint)pre_draw->chg_length, (jint)pre_draw->caret, awt_util_nowMillisUTC()); + + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + finally: AWT_UNLOCK(); return; } static void PreeditCaretCallback(XIC ic, XPointer client_data, XIMPreeditCaretCallbackStruct *pre_caret) { ! XIMPreeditDrawCallbackStruct pre_draw; + if (pre_caret != NULL && pre_caret->direction == XIMAbsolutePosition) { + pre_draw.caret = pre_caret->position; + pre_draw.chg_first = 0; + pre_draw.chg_length = 0; + pre_draw.text = NULL; + PreeditDrawCallback(ic, client_data, &pre_draw); + } } static void StatusStartCallback(XIC ic, XPointer client_data, XPointer call_data) { /*ARGSUSED*/ /*printf("StatusStartCallback:\n"); */ } static void StatusDoneCallback(XIC ic, XPointer client_data, XPointer call_data) { /*ARGSUSED*/ /*printf("StatusDoneCallback:\n"); */ } ! static void StatusDrawCallback ! (XIC ic, XPointer client_data, XIMStatusDrawCallbackStruct *status_draw) { /*ARGSUSED*/ /*printf("StatusDrawCallback:\n"); */ JNIEnv *env = GetJNIEnv(); X11InputMethodData *pX11IMData = NULL; StatusWindow *statusWindow; + int value_make = CWX|CWWidth|CWHeight; + XRectangle logical, ink; + XWindowChanges xwc; + int len; AWT_LOCK(); if (NULL == (pX11IMData = getX11InputMethodData(env, (jobject)client_data)) || NULL == (statusWindow = pX11IMData->statusWindow)){ goto finally; } ! if (status_draw->type == XIMTextType) { XIMText *text = (status_draw->data).text; ! if (text != NULL) { ! if (text->string.multi_byte != NULL) { ! if(!strcmp(text->string.multi_byte," ")){ ! wcscpy(statusWindow->status, L""); ! onoffStatusWindow(pX11IMData, 0, False); ! goto finally; ! } ! mbstowcs(statusWindow->status, ! (const char *)text->string.multi_byte, ! (size_t)MAX_STATUS_LEN); ! } else { ! if (0 == st_wcslen(text->string.wide_char)){ ! wcscpy(statusWindow->status, L""); ! onoffStatusWindow(pX11IMData, 0, False); ! goto finally; ! } ! wcsncpy(statusWindow->status, ! text->string.wide_char, ! MAX_STATUS_LEN); ! } ! XwcTextExtents(statusWindow->fontset, statusWindow->status, ! st_wcslen(statusWindow->status), &ink, &logical); ! statusWindow->statusW = logical.width + BORDER_MARGIN; ! statusWindow->statusH = logical.height + BORDER_MARGIN; ! xwc.x = statusWindow->x - statusWindow->off_x; ! if (xwc.x < 0 ) xwc.x = 0; ! xwc.width = statusWindow->statusW; ! xwc.height = statusWindow->statusH; ! if (xwc.x + xwc.width > statusWindow->rootW){ ! xwc.x = statusWindow->rootW - xwc.width; ! } ! XConfigureWindow(dpy, statusWindow->w, value_make, &xwc); ! if (statusWindow->status_ready && statusWindow->on == True){ ! onoffStatusWindow(pX11IMData, statusWindow->parent, True); } ! paintStatusWindow(statusWindow); ! if (statusWindow->peText) ! draw_preedit(statusWindow); } else { ! wcscpy(statusWindow->status, L""); /*just turnoff the status window paintStatusWindow(statusWindow); */ onoffStatusWindow(pX11IMData, 0, False); } } finally: AWT_UNLOCK(); } ! /* return the string length without trailing spaces */ ! /* work around code for Japanese AIXIM is implemented. */ ! static int st_wcslen(wchar_t *string) ! { ! int len = (int32_t)wcslen(string); ! if (len == 0) ! return 0; ! for (len--;len >= 0; len--) { ! if (!iswspace((wint_t) string[len])) break; ! } ! return len+1; ! } ! /* ! * Checks whether given XIMText contains a string data. ! */ ! static Bool is_text_available(XIMText * text) ! { ! if (text == NULL || text->length==0) ! return False; ! if (text->encoding_is_wchar) { ! if(text->string.wide_char[0] == L'\0') ! return False; ! } else { ! if (text->string.multi_byte[0] == '\0') ! return False; ! } ! return True; ! } ! /* ! * check if preedit status is active ! */ ! static Bool isPreeditStateActive(XIC ic) ! { ! XIMPreeditState state = XIMPreeditUnKnown; ! XVaNestedList pr_atrb; ! char* nosupportAttr; ! ! if (ic == NULL) return False; ! ! pr_atrb = XVaCreateNestedList(0,XNPreeditState,&state,NULL); ! nosupportAttr=XGetICValues(ic,XNPreeditAttributes,pr_atrb,NULL); ! XFree(pr_atrb); ! if (nosupportAttr==NULL && state & XIMPreeditDisable) ! return False; ! else ! return True; ! } ! ! static void * buf_insert(void * src, void * insert, int size, ! int src_len, int ins_len, int offset) ! { ! char *temp; ! ! temp = realloc(src, size*(src_len+ins_len+1)); ! if (temp == NULL) { ! THROW_OUT_OF_MEMORY_ERROR(); ! return src; ! } ! if (offset != src_len) { ! memmove(&temp[size*(offset+ins_len)], ! &((char *)temp)[size*offset], ! size*(src_len-offset)); } + memcpy(&temp[size*offset], insert, size*ins_len); ! return (void *)temp; ! } ! ! static void * handle_buffer(void * source, void * insert, ! int size,int src_len, int ins_len, ! int del_len, int offset) ! { ! void * temp = source; ! ! if (del_len > 0) { ! if (del_len == ins_len) { ! memcpy(&((char *)source)[size*offset], insert, size*ins_len); ! return source; ! } ! else if (src_len > offset+del_len) { ! memmove(&((char *)source)[size*offset], ! &((char *)source)[size*(offset+del_len)], ! size*(src_len-offset-del_len)); ! } } ! if (ins_len > 0) { ! temp = buf_insert(source, insert, size, src_len, ! ins_len, offset); ! } ! return temp; ! } ! /* ! * Display the given preedit text to the root window which is ownd by ! * myself. All of the character is converted to wide char. ! * this function is used for the passive client. ! */ ! static void preedit_draw_passive(X11InputMethodData *pX11IMData, ! XIMPreeditDrawCallbackStruct *pre_draw) ! { ! XIMText *text; ! wchar_t *tempbuf = NULL; ! StatusWindow *statusWindow; ! wchar_t *cur_text; ! unsigned long *cur_attr; ! int cur_len = 0; ! int chg_len = pre_draw->chg_length; ! int chg_1st = pre_draw->chg_first; ! if (NULL == (statusWindow = pX11IMData->statusWindow)) ! return; ! cur_text = statusWindow->peText; ! cur_attr = statusWindow->peAttr; ! if (cur_text == NULL && pre_draw->text == NULL) ! return; ! ! if (cur_text != NULL) ! cur_len = (int32_t)wcslen(cur_text); ! text = pre_draw->text; ! if (text == NULL) { ! /* delete only */ ! if (cur_len > chg_1st+chg_len) { ! memmove(&cur_text[chg_1st], ! &cur_text[chg_1st+chg_len], ! sizeof(wchar_t)*(cur_len-chg_1st-chg_len)); ! memmove(&cur_attr[chg_1st], ! &cur_attr[chg_1st+chg_len], ! sizeof(long)*(cur_len-chg_1st-chg_len)); ! } ! if ((pre_draw->chg_length <= cur_len ) && (pre_draw->chg_length >0)) ! cur_text[cur_len-pre_draw->chg_length] =L'\0'; } else { ! /* insert or replace */ ! int ins_len = 0; ! void * ins_text = NULL; ! ! /* if invalid offset is specified, do nothing. */ ! /* this fix is for aixim for eucTW */ ! if (cur_len < chg_1st) ! return; ! if(is_text_available(text)) { ! /* insert or replace the text */ ! if (text->encoding_is_wchar == False) { ! /* convert the text to wide chars. ! allocate enough size buffer ! */ ! tempbuf = (wchar_t *)malloc(sizeof(wchar_t)*(text->length+1)); ! if (tempbuf == NULL) { ! THROW_OUT_OF_MEMORY_ERROR(); ! return; ! } ! ins_len = (int32_t)mbstowcs(tempbuf, text->string.multi_byte, ! text->length); ! if (ins_len == -1) { ! free(tempbuf); ! return; ! } ! ins_text = (void *)tempbuf; ! } ! else { ! ins_len = text->length; ! ins_text = text->string.wide_char; ! } ! /* finish prepare the data to be inserted */ ! ! statusWindow->peText = ! handle_buffer(cur_text, ins_text, sizeof(wchar_t), ! cur_len, ins_len, chg_len, chg_1st); ! statusWindow->peAttr = ! handle_buffer(cur_attr, text->feedback, sizeof(long), ! cur_len, ins_len, chg_len, chg_1st); ! statusWindow->peText[cur_len-chg_len+ins_len] =L'\0'; ! ! if (tempbuf != NULL) ! free(tempbuf); ! } /* endof insert or replace text */ ! else { ! /* change attribute only */ ! memcpy(&cur_attr[chg_1st], text->feedback, ! sizeof(long)*text->length); } } + statusWindow->peCaret= pre_draw->caret; + draw_preedit(statusWindow); + if (statusWindow->on && wcslen(statusWindow->peText) > 0) + onoffStatusWindow(pX11IMData, statusWindow->parent, True); + else if (wcslen(statusWindow->status) == 0) + onoffStatusWindow(pX11IMData, 0, False); + } ! /* ! * reset predit test of passive mode ! */ ! static void ! resetPassivePreeditText(StatusWindow *statusWindow) ! { ! if (NULL == statusWindow) return; ! if(statusWindow->peText != NULL) { ! free(statusWindow->peText); ! statusWindow->peText = NULL; } ! if(statusWindow->peAttr != NULL) { ! free(statusWindow->peAttr); ! statusWindow->peAttr = NULL; ! } ! statusWindow->peCaret= 0; } ! static void draw_caret(StatusWindow *statusWindow, GC gc, int pos) ! { ! if (NULL == statusWindow) return; ! XSetFunction(dpy, gc, GXinvert); ! XDrawLine(dpy, statusWindow->w, ! gc, pos, STATUS_BORDER/2, ! pos, STATUS_BORDER/2+statusWindow->fOff); ! XSetFunction(dpy, gc, GXcopy); ! } ! static int get_next_attr(int len, unsigned long *attr) ! { ! int count; ! ! for (count = 1; count < len; count++) { ! if ((attr[count-1] & PREEDIT_ATTR_MASK) ! != (attr[count] & PREEDIT_ATTR_MASK)) ! break; ! } ! return count; ! } ! ! static void draw_preedit(StatusWindow *statusWindow) ! { ! unsigned long *attr; ! int x_pos,x_caret; ! unsigned int len; ! int len_disp, pos; ! wchar_t *str; ! GC gc; ! XRectangle ink, rect, rect_c; ! Bool caret_done = False; ! ! if (NULL == statusWindow) return; ! align_status(statusWindow); ! XFillRectangle(dpy, statusWindow->w, ! statusWindow->bgGC, ! statusWindow->statusW,0, ! statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN, ! statusWindow->fBot+2); ! ! ! XDrawLine(dpy, statusWindow->w, statusWindow->fgGC, ! statusWindow->statusW, 0, ! statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN, 0); ! XDrawLine(dpy, statusWindow->w, statusWindow->fgGC, ! statusWindow->statusW, statusWindow->fBot+2, ! statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN, ! statusWindow->fBot+2); ! XDrawLine(dpy, statusWindow->w, statusWindow->fgGC, ! statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN, 0, ! statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN, ! statusWindow->fBot+2); ! if (0 == statusWindow->statusW) ! XDrawLine(dpy, statusWindow->w, statusWindow->fgGC, ! 0, 0, 0, statusWindow->fBot+2); ! ! str = statusWindow->peText; ! ! if (str != NULL && (len = (int32_t)wcslen(str)) != 0) { ! pos = 0; ! attr = statusWindow->peAttr; ! x_pos = x_caret = statusWindow->statusW + STATUS_BORDER; ! while((int)len-1 >= pos) { ! len_disp = get_next_attr(len - pos, &attr[pos]); ! if (attr[pos] & XIMReverse) { ! gc = statusWindow->bgGC; ! } ! else { ! gc = statusWindow->fgGC; ! } ! XwcTextExtents(statusWindow->fontset, ! &str[pos], ! len_disp, &ink, &rect); ! XwcDrawImageString(dpy, statusWindow->w, ! statusWindow->fontset, gc, ! x_pos, statusWindow->fOff+1, &str[pos], len_disp); ! if (attr[pos] & XIMUnderline) { ! XDrawLine(dpy, statusWindow->w, ! gc, x_pos, statusWindow->fBot, ! x_pos+rect.width, statusWindow->fBot); ! } ! if (!caret_done) { ! if( statusWindow->peCaret >= pos && ! statusWindow->peCaret <= pos+len_disp) { ! if (statusWindow->peCaret == 0) ! x_caret = x_pos; ! else if (statusWindow->peCaret == pos+len_disp) ! x_caret = x_pos+rect.width; ! else { ! XwcTextExtents(statusWindow->fontset, ! &str[pos], ! statusWindow->peCaret-pos, ! &ink, &rect_c); ! x_caret = x_pos+ rect_c.width; ! } ! x_caret-=CARET_OFFSET; ! caret_done = True; ! } ! } ! pos += len_disp; ! x_pos += rect.width; ! } ! if (caret_done) ! draw_caret(statusWindow, statusWindow->fgGC, x_caret); ! } ! } ! ! /* calc required status window size and resize the window */ ! static void align_status(StatusWindow *statusWindow) ! { ! int len_st, len_pe = 0; ! XRectangle rect_st, rect_pe, ink; ! Dimension cur_w; ! int value_make = CWX|CWWidth|CWHeight; ! XWindowChanges xwc; ! ! if (NULL == statusWindow) return; ! if ((len_st = st_wcslen(statusWindow->status)) == 0 ! && (statusWindow->peText == NULL || st_wcslen(statusWindow->peText) == 0 )) return; + + rect_pe.x = rect_pe.y = rect_pe.width = rect_pe.height = 0; + + XwcTextExtents(statusWindow->fontset, + statusWindow->status, + len_st, &ink, &rect_st); + if (statusWindow->peText != NULL + && (len_pe = (int32_t)wcslen(statusWindow->peText)) > 0) { + XwcTextExtents(statusWindow->fontset, + statusWindow->peText, + len_pe, &ink, &rect_pe); + } + statusWindow->fOff = max(-rect_st.y, -rect_pe.y); + statusWindow->fBot = max(rect_st.height, rect_pe.height); + statusWindow->statusW =rect_st.width; + if (rect_st.width > 0) statusWindow->statusW += BORDER_MARGIN; + statusWindow->peTextW = rect_pe.width; + + xwc.x = statusWindow->x - statusWindow->off_x; + if (xwc.x < 0 ) xwc.x = 0; + + if (len_pe > 0) { + xwc.width = statusWindow->statusW + + statusWindow->peTextW + BORDER_MARGIN + 1; + xwc.height = statusWindow->fBot + BORDER_MARGIN; + } else { + xwc.width = statusWindow->statusW; + xwc.height = statusWindow->fBot + BORDER_MARGIN; + } + if (xwc.x + xwc.width > statusWindow->rootW){ + xwc.x = statusWindow->rootW - xwc.width; } + XConfigureWindow(dpy, statusWindow->w, value_make, &xwc); + } + + static void shrink_status(StatusWindow *statusWindow) + { + int value_make = CWX|CWWidth|CWHeight; + XWindowChanges xwc; ! if (NULL == statusWindow) return; ! xwc.width = statusWindow->statusW; ! xwc.height = statusWindow->statusH; ! statusWindow->peTextW = 0; ! xwc.x = statusWindow->x - statusWindow->off_x; ! if (xwc.x < 0 ) xwc.x = 0; ! if (xwc.x + xwc.width > statusWindow->rootW){ ! xwc.x = statusWindow->rootW - xwc.width; ! } ! XConfigureWindow(dpy, statusWindow->w, value_make, &xwc); } ! static GC create_gc(Window win, Bool isReverse) ! { ! XGCValues xgcv; ! unsigned long mask; ! AwtScreenDataPtr defaultScreen; ! ! defaultScreen = getScreenData(DefaultScreen(dpy)); ! ! mask = (GCForeground | GCBackground ); ! if (isReverse) { ! xgcv.foreground = defaultScreen->whitepixel; ! xgcv.background = defaultScreen->blackpixel; ! } else { ! xgcv.foreground = defaultScreen->blackpixel; ! xgcv.background = defaultScreen->whitepixel; ! } ! return XCreateGC(dpy, win, mask, &xgcv); } ! static Bool isNativeIm() ! { ! #define XIMMODIFIER "@im=" ! #define XIM_SERVER_CATEGORY "@server=" ! char *immodifiers; ! char *imserver, *imserverPtr; ! Atom imserverAtom; ! ! if (!(immodifiers = getenv("XMODIFIERS"))) return True; ! if (!(imserver = calloc(1,strlen(immodifiers)+strlen(XIM_SERVER_CATEGORY)+1))) return True; ! if (!(immodifiers = strstr(immodifiers,XIMMODIFIER))) return True; ! immodifiers += strlen(XIMMODIFIER); ! strcpy(imserver,XIM_SERVER_CATEGORY); ! imserverPtr = imserver + strlen(imserver); ! while(*immodifiers != '@' && *immodifiers != '\0') { ! *imserverPtr = *immodifiers; ! imserverPtr++; ! immodifiers++; ! } ! imserverAtom = XInternAtom(awt_display, imserver, True); ! free(imserver); ! if (imserverAtom > 0) ! return False; ! else ! return True; ! } ! static Window getGrandParent(Window parent) { ! Window containerWindow,rootWindow,tmp; ! Window *ignoreWindowPtr; ! unsigned int ignoreUnit; ! Window grandParent=0; ! XWindowAttributes xwa; ! Atom WM_STATE; ! Atom type = None; ! int32_t format; ! unsigned long nitems, after; ! unsigned char * data; ! ! if (parent == 0) return grandParent; ! WM_STATE = XInternAtom(dpy, "WM_STATE", True); ! if (WM_STATE == None) return grandParent; ! ! tmp=parent; ! while(XQueryTree(dpy, tmp, ! &rootWindow, &containerWindow, ! &ignoreWindowPtr, &ignoreUnit)){ ! XFree(ignoreWindowPtr); ! if (containerWindow == rootWindow) break; ! if (XGetWindowProperty(dpy, containerWindow, WM_STATE, ! 0, 0, False, AnyPropertyType, ! &type, &format, &nitems, &after, &data) == Success) { ! XFree(data); ! if (type) { ! XGetWindowAttributes(dpy, containerWindow, &xwa); ! if (FALSE == xwa.override_redirect){ ! grandParent=containerWindow; ! } ! } ! } ! tmp=containerWindow; ! } ! return grandParent; } + static void moveStatusWindow(StatusWindow *statusWindow) + { + XWindowAttributes xwa; + Window child; + int x, y, width; + Window target; + + if (NULL == statusWindow) return; + if (statusWindow->grandParent) { + target = statusWindow->grandParent; + } else { + target = statusWindow->parent; + } + XGetWindowAttributes(dpy, target, &xwa); + XTranslateCoordinates(dpy, + target, xwa.root, + 0, 0, + &x, &y, + &child); + if (statusWindow->x != x + || statusWindow->y != y + || statusWindow->width != xwa.width + || statusWindow->height != xwa.height){ + statusWindow->x = x; + statusWindow->y = y; + statusWindow->height = xwa.height; + statusWindow->width = xwa.width; + x = statusWindow->x - statusWindow->off_x; + y = statusWindow->y + statusWindow->height + statusWindow->off_y; + if (x < 0 ){ + x = 0; + } + if (statusWindow->peTextW > 0) { + width = statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN + 1; + if (x + width > statusWindow->rootW){ + x = statusWindow->rootW - width; + } + } else { + if (x + statusWindow->statusW > statusWindow->rootW){ + x = statusWindow->rootW - statusWindow->statusW; + } + } + if (y + statusWindow->statusH > statusWindow->rootH){ + y = statusWindow->rootH - statusWindow->statusH; + } + XMoveWindow(dpy, statusWindow->w, x, y); + } + } + + static void arrange_window_stack(StatusWindow* statusWindow) + { + XWindowChanges xwc; + int value_make = CWSibling|CWStackMode; + Window root, parent, *children; + unsigned int nchildren; + + if (NULL == statusWindow) return; + if (XQueryTree(dpy, statusWindow->parent, + &root, &parent, &children, &nchildren)){ + XFree(children); + xwc.sibling = parent; + while(XQueryTree(dpy, xwc.sibling, &root, &parent, &children, &nchildren)) { + XFree(children); + if (root != parent) { + xwc.sibling = parent; + } else { + break; + } + } + xwc.stack_mode = Above; + XConfigureWindow(dpy, statusWindow->w, value_make, &xwc); + } + } + + static int count_missing_fonts(char **charset_list, int charset_count) + { + int i,j; + if (charset_count > 0) { + j=charset_count; + for(i=0; i < charset_count; i++) { + if ((strstr(charset_list[i], "IBM-udc")) || + (strstr(charset_list[i], "IBM-sbd")) || + (strstr(charset_list[i], "IBM-ucdTW"))) + j--; + } + return j; + } + else + return 0; + } + + static XFontSet create_fontset_name(char * font_name, Bool force) + { + XFontSet fontset = NULL; + char **charset_list; + int charset_count; + char *def_string; + int missing_fonts; + + fontset = XCreateFontSet(dpy, font_name, + &charset_list, &charset_count, &def_string); + if (charset_count > 0) { + missing_fonts = count_missing_fonts(charset_list, + charset_count); + XFreeStringList(charset_list); + if (fontset && (missing_fonts > 0)) { + if (!force) { + XFreeFontSet(dpy, fontset); + fontset = NULL; + } + } + } + return fontset; + } + + static XFontSet create_fontset() + { + XFontSet fontset = NULL; + int i; + static char * fontlist[] = { + "-dt-interface user-medium-r-normal-S*-*-*-*-*-*-*-*-*", + "-*-*-medium-r-normal-*-14-*-*-*-c-*-*-*", + "-*-*-medium-r-normal-*-14-*-*-*-m-*-*-*", + "-*-*-medium-r-normal--14-0-0-0-m-*-*-*", + "-monotype-sansmonowt-medium-r-normal--14-*-*-*-m-*-*-*", + "-*--14-*", + "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*", + "-*--16-*", + "-*--17-*", + "-*--18-*", + "-*--19-*", + "-*--20-*", + "-*--24-*", + NULL}; + + for (i=0; fontlist[i] != NULL && fontset==NULL; i++) + fontset = create_fontset_name(fontlist[i], False); + + if (!fontset) + fprintf(stdout, "Cannot load fonts for IMF.\n"); + return fontset; + } + + static Window get_current_focus(XIC ic) { + Window w = 0; + if (ic != NULL) + XGetICValues(ic, XNFocusWindow, &w, NULL); + return w; + } JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XInputMethod_openXIMNative(JNIEnv *env, ! jobject this, ! jlong display) { Bool registered; AWT_LOCK(); dpy = (Display *)jlong_to_ptr(display); ! if (X11im == NULL) { ! X11im = XOpenIM(dpy, NULL, NULL, NULL); } AWT_UNLOCK(); return JNI_TRUE; } JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XInputMethod_createXICNative(JNIEnv *env, ! jobject this, ! jlong window) { X11InputMethodData *pX11IMData; jobject globalRef; XIC ic;
*** 1397,1434 **** return JNI_FALSE; } globalRef = (*env)->NewGlobalRef(env, this); pX11IMData->x11inputmethod = globalRef; - #if defined(__linux__) || defined(MACOSX) pX11IMData->statusWindow = NULL; - #endif /* __linux__ || MACOSX */ ! pX11IMData->lookup_buf = 0; ! pX11IMData->lookup_buf_len = 0; if (createXIC(env, pX11IMData, (Window)window) == False) { destroyX11InputMethodData((JNIEnv *) NULL, pX11IMData); pX11IMData = (X11InputMethodData *) NULL; if ((*env)->ExceptionCheck(env)) { goto finally; } } - setX11InputMethodData(env, this, pX11IMData); - finally: AWT_UNLOCK(); return (pX11IMData != NULL); } JNIEXPORT void JNICALL Java_sun_awt_X11_XInputMethod_setXICFocusNative(JNIEnv *env, ! jobject this, ! jlong w, ! jboolean req, ! jboolean active) { X11InputMethodData *pX11IMData; AWT_LOCK(); pX11IMData = getX11InputMethodData(env, this); if (pX11IMData == NULL) { --- 1935,1968 ---- return JNI_FALSE; } globalRef = (*env)->NewGlobalRef(env, this); pX11IMData->x11inputmethod = globalRef; pX11IMData->statusWindow = NULL; ! setX11InputMethodData(env, this, pX11IMData); if (createXIC(env, pX11IMData, (Window)window) == False) { destroyX11InputMethodData((JNIEnv *) NULL, pX11IMData); pX11IMData = (X11InputMethodData *) NULL; + setX11InputMethodData(env, this, pX11IMData); if ((*env)->ExceptionCheck(env)) { goto finally; } } finally: AWT_UNLOCK(); return (pX11IMData != NULL); } JNIEXPORT void JNICALL Java_sun_awt_X11_XInputMethod_setXICFocusNative(JNIEnv *env, ! jobject this, ! jlong w, ! jboolean req, ! jboolean active) { X11InputMethodData *pX11IMData; AWT_LOCK(); pX11IMData = getX11InputMethodData(env, this); if (pX11IMData == NULL) {
*** 1439,1505 **** if (req) { if (!w) { AWT_UNLOCK(); return; } pX11IMData->current_ic = active ? pX11IMData->ic_active : pX11IMData->ic_passive; /* * On Solaris2.6, setXICWindowFocus() has to be invoked * before setting focus. */ ! setXICWindowFocus(pX11IMData->current_ic, w); ! setXICFocus(pX11IMData->current_ic, req); ! currentX11InputMethodInstance = pX11IMData->x11inputmethod; ! currentFocusWindow = w; ! #if defined(__linux__) || defined(MACOSX) ! if (active && pX11IMData->statusWindow && pX11IMData->statusWindow->on) onoffStatusWindow(pX11IMData, w, True); - #endif } else { currentX11InputMethodInstance = NULL; currentFocusWindow = 0; - #if defined(__linux__) || defined(MACOSX) onoffStatusWindow(pX11IMData, 0, False); if (pX11IMData->current_ic != NULL) - #endif setXICFocus(pX11IMData->current_ic, req); pX11IMData->current_ic = (XIC)0; } XFlush(dpy); AWT_UNLOCK(); } ! JNIEXPORT void JNICALL ! Java_sun_awt_X11InputMethod_turnoffStatusWindow(JNIEnv *env, ! jobject this) { - #if defined(__linux__) || defined(MACOSX) X11InputMethodData *pX11IMData; StatusWindow *statusWindow; AWT_LOCK(); if (NULL == currentX11InputMethodInstance - || !isX11InputMethodGRefInList(currentX11InputMethodInstance) || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance)) || NULL == (statusWindow = pX11IMData->statusWindow) || !statusWindow->on ){ AWT_UNLOCK(); return; } onoffStatusWindow(pX11IMData, 0, False); AWT_UNLOCK(); - #endif } ! JNIEXPORT void JNICALL ! Java_sun_awt_X11InputMethod_disposeXIC(JNIEnv *env, ! jobject this) { X11InputMethodData *pX11IMData = NULL; AWT_LOCK(); pX11IMData = getX11InputMethodData(env, this); --- 1973,2062 ---- if (req) { if (!w) { AWT_UNLOCK(); return; } + pX11IMData->isActiveClient = active; pX11IMData->current_ic = active ? pX11IMData->ic_active : pX11IMData->ic_passive; /* * On Solaris2.6, setXICWindowFocus() has to be invoked * before setting focus. */ ! get_current_focus(pX11IMData->current_ic); /* workaround for kinput2 and SCIM */ ! if (currentFocusWindow != w) { ! setXICWindowFocus(pX11IMData->current_ic, w); ! setXICFocus(pX11IMData->current_ic, req); ! currentX11InputMethodInstance = pX11IMData->x11inputmethod; ! currentFocusWindow = w; ! } else { ! setXICFocus(pX11IMData->current_ic, req); ! } ! if ((active || pX11IMData->passiveStatusWindow) ! && (pX11IMData->statusWindow && pX11IMData->statusWindow->on)) onoffStatusWindow(pX11IMData, w, True); } else { currentX11InputMethodInstance = NULL; currentFocusWindow = 0; onoffStatusWindow(pX11IMData, 0, False); if (pX11IMData->current_ic != NULL) setXICFocus(pX11IMData->current_ic, req); pX11IMData->current_ic = (XIC)0; } XFlush(dpy); AWT_UNLOCK(); } ! /* ! * Class: sun_awt_X11InputMethodBase ! * Method: initIDs ! * Signature: ()V ! * This function gets called from the static initializer for ! * X11InputMethod.java to initialize the fieldIDs for fields ! * that may be accessed from C ! */ ! JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_initIDs ! (JNIEnv *env, jclass cls) ! { ! x11InputMethodIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J"); ! } ! ! /* ! * Class: sun_awt_X11InputMethodBase ! * Method: turnoffStatusWindow ! * Signature: ()V ! */ ! JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_turnoffStatusWindow ! (JNIEnv *env, jobject this) { X11InputMethodData *pX11IMData; StatusWindow *statusWindow; AWT_LOCK(); if (NULL == currentX11InputMethodInstance || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance)) || NULL == (statusWindow = pX11IMData->statusWindow) || !statusWindow->on ){ AWT_UNLOCK(); return; } onoffStatusWindow(pX11IMData, 0, False); + statusWindow->on = False; AWT_UNLOCK(); } ! /* ! * Class: sun_awt_X11InputMethodBase ! * Method: disposeXIC ! * Signature: ()V ! */ ! JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_disposeXIC ! (JNIEnv *env, jobject this) { X11InputMethodData *pX11IMData = NULL; AWT_LOCK(); pX11IMData = getX11InputMethodData(env, this);
*** 1516,1528 **** } destroyX11InputMethodData(env, pX11IMData); AWT_UNLOCK(); } ! JNIEXPORT jstring JNICALL ! Java_sun_awt_X11InputMethod_resetXIC(JNIEnv *env, ! jobject this) { X11InputMethodData *pX11IMData; char *xText = NULL; jstring jText = (jstring)0; --- 2073,2089 ---- } destroyX11InputMethodData(env, pX11IMData); AWT_UNLOCK(); } ! /* ! * Class: sun_awt_X11InputMethodBase ! * Method: resetXIC ! * Signature: ()Ljava/lang/String; ! */ ! JNIEXPORT jstring JNICALL Java_sun_awt_X11InputMethodBase_resetXIC ! (JNIEnv *env, jobject this) { X11InputMethodData *pX11IMData; char *xText = NULL; jstring jText = (jstring)0;
*** 1531,1651 **** if (pX11IMData == NULL) { AWT_UNLOCK(); return jText; } ! if (pX11IMData->current_ic) ! xText = XmbResetIC(pX11IMData->current_ic); ! else { /* * If there is no reference to the current XIC, try to reset both XICs. */ xText = XmbResetIC(pX11IMData->ic_active); /*it may also means that the real client component does not have focus -- has been deactivated... its xic should not have the focus, bug#4284651 showes reset XIC for htt may bring the focus back, so de-focus it again. */ setXICFocus(pX11IMData->ic_active, FALSE); if (pX11IMData->ic_active != pX11IMData->ic_passive) { ! char *tmpText = XmbResetIC(pX11IMData->ic_passive); setXICFocus(pX11IMData->ic_passive, FALSE); if (xText == (char *)NULL && tmpText) xText = tmpText; } - } if (xText != NULL) { jText = JNU_NewStringPlatform(env, (const char *)xText); XFree((void *)xText); } AWT_UNLOCK(); return jText; } /* ! * Class: sun_awt_X11InputMethod * Method: setCompositionEnabledNative ! * Signature: (ZJ)V * * This method tries to set the XNPreeditState attribute associated with the current * XIC to the passed in 'enable' state. * * Return JNI_TRUE if XNPreeditState attribute is successfully changed to the * 'enable' state; Otherwise, if XSetICValues fails to set this attribute, * java.lang.UnsupportedOperationException will be thrown. JNI_FALSE is returned if this * method fails due to other reasons. - * */ ! JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethod_setCompositionEnabledNative (JNIEnv *env, jobject this, jboolean enable) { X11InputMethodData *pX11IMData; char * ret = NULL; AWT_LOCK(); pX11IMData = getX11InputMethodData(env, this); if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) { AWT_UNLOCK(); return JNI_FALSE; } ! ret = XSetICValues(pX11IMData->current_ic, XNPreeditState, ! (enable ? XIMPreeditEnable : XIMPreeditDisable), NULL); AWT_UNLOCK(); ! if ((ret != 0) && (strcmp(ret, XNPreeditState) == 0)) { JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", ""); } return (jboolean)(ret == 0); } /* ! * Class: sun_awt_X11InputMethod * Method: isCompositionEnabledNative ! * Signature: (J)Z * * This method tries to get the XNPreeditState attribute associated with the current XIC. * * Return JNI_TRUE if the XNPreeditState is successfully retrieved. Otherwise, if * XGetICValues fails to get this attribute, java.lang.UnsupportedOperationException * will be thrown. JNI_FALSE is returned if this method fails due to other reasons. - * */ ! JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethod_isCompositionEnabledNative (JNIEnv *env, jobject this) { X11InputMethodData *pX11IMData = NULL; char * ret = NULL; ! XIMPreeditState state; AWT_LOCK(); pX11IMData = getX11InputMethodData(env, this); if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) { AWT_UNLOCK(); return JNI_FALSE; } ! ret = XGetICValues(pX11IMData->current_ic, XNPreeditState, &state, NULL); AWT_UNLOCK(); ! if ((ret != 0) && (strcmp(ret, XNPreeditState) == 0)) { JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", ""); return JNI_FALSE; } return (jboolean)(state == XIMPreeditEnable); } JNIEXPORT void JNICALL Java_sun_awt_X11_XInputMethod_adjustStatusWindow (JNIEnv *env, jobject this, jlong window) { ! #if defined(__linux__) || defined(MACOSX) ! AWT_LOCK(); ! adjustStatusWindow(window); ! AWT_UNLOCK(); ! #endif } --- 2092,2269 ---- if (pX11IMData == NULL) { AWT_UNLOCK(); return jText; } ! if (pX11IMData->current_ic) { ! if (!isPreeditStateActive(pX11IMData->current_ic)) { ! xText = NULL; ! } else { ! if (!(pX11IMData->forceReset)) ! setXICFocus(pX11IMData->current_ic, FALSE); ! xText = XmbResetIC(pX11IMData->current_ic); ! if (!(pX11IMData->forceReset)) ! setXICFocus(pX11IMData->current_ic, TRUE); ! } ! } else { /* * If there is no reference to the current XIC, try to reset both XICs. */ + if (!isPreeditStateActive(pX11IMData->ic_active)) + xText = NULL; + else xText = XmbResetIC(pX11IMData->ic_active); /*it may also means that the real client component does not have focus -- has been deactivated... its xic should not have the focus, bug#4284651 showes reset XIC for htt may bring the focus back, so de-focus it again. */ setXICFocus(pX11IMData->ic_active, FALSE); if (pX11IMData->ic_active != pX11IMData->ic_passive) { ! char *tmpText; ! if (!isPreeditStateActive(pX11IMData->ic_passive)) ! tmpText = NULL; ! else ! tmpText = XmbResetIC(pX11IMData->ic_passive); setXICFocus(pX11IMData->ic_passive, FALSE); if (xText == (char *)NULL && tmpText) xText = tmpText; } } if (xText != NULL) { jText = JNU_NewStringPlatform(env, (const char *)xText); XFree((void *)xText); } + /* workaround + * Some IME do not call PreeditDoneCallback routine even + * when XmbResetIC is called. I force to reset the preedit string. + */ + if (!pX11IMData->isActiveClient) { + resetPassivePreeditText(pX11IMData->statusWindow); + shrink_status(pX11IMData->statusWindow); + } else { + JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod, + "clearComposedText", + "()V"); + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + } + AWT_UNLOCK(); return jText; } /* ! * Class: sun_awt_X11InputMethodBase * Method: setCompositionEnabledNative ! * Signature: (Z)Z * * This method tries to set the XNPreeditState attribute associated with the current * XIC to the passed in 'enable' state. * * Return JNI_TRUE if XNPreeditState attribute is successfully changed to the * 'enable' state; Otherwise, if XSetICValues fails to set this attribute, * java.lang.UnsupportedOperationException will be thrown. JNI_FALSE is returned if this * method fails due to other reasons. */ ! JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_setCompositionEnabledNative (JNIEnv *env, jobject this, jboolean enable) { X11InputMethodData *pX11IMData; char * ret = NULL; + XVaNestedList pr_atrb; AWT_LOCK(); pX11IMData = getX11InputMethodData(env, this); if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) { AWT_UNLOCK(); return JNI_FALSE; } ! pr_atrb = XVaCreateNestedList(0, XNPreeditState, ! (enable ? XIMPreeditEnable : XIMPreeditDisable), NULL); ! ret = XSetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL); ! XFree((void *)pr_atrb); AWT_UNLOCK(); ! if ((ret != 0) && ! ((strcmp(ret, XNPreeditAttributes) == 0) ! || (strcmp(ret, XNPreeditState) == 0))) { JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", ""); } return (jboolean)(ret == 0); } /* ! * Class: sun_awt_X11InputMethodBase * Method: isCompositionEnabledNative ! * Signature: ()Z * * This method tries to get the XNPreeditState attribute associated with the current XIC. * * Return JNI_TRUE if the XNPreeditState is successfully retrieved. Otherwise, if * XGetICValues fails to get this attribute, java.lang.UnsupportedOperationException * will be thrown. JNI_FALSE is returned if this method fails due to other reasons. */ ! JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_isCompositionEnabledNative (JNIEnv *env, jobject this) { X11InputMethodData *pX11IMData = NULL; char * ret = NULL; ! XIMPreeditState state = XIMPreeditUnKnown; ! XVaNestedList pr_atrb; AWT_LOCK(); pX11IMData = getX11InputMethodData(env, this); if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) { AWT_UNLOCK(); return JNI_FALSE; } ! pr_atrb = XVaCreateNestedList(0, XNPreeditState, &state, NULL); ! ret = XGetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL); ! XFree((void *)pr_atrb); AWT_UNLOCK(); ! if ((ret != 0) && ! ((strcmp(ret, XNPreeditAttributes) == 0) ! || (strcmp(ret, XNPreeditState) == 0))) { JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", ""); return JNI_FALSE; } return (jboolean)(state == XIMPreeditEnable); } JNIEXPORT void JNICALL Java_sun_awt_X11_XInputMethod_adjustStatusWindow (JNIEnv *env, jobject this, jlong window) { ! ! } ! ! /* ! * Class: sun_awt_X11InputMethod ! * Method: setStatusAreaVisible ! * Signature: (ZJ)V ! */ ! JNIEXPORT void JNICALL Java_sun_awt_X11InputMethod_setStatusAreaVisible ! (JNIEnv *env, jobject this, jboolean value, jlong data) ! { ! X11InputMethodData *pX11IMData; ! ! pX11IMData = getX11InputMethodData(env, this); ! if (NULL == pX11IMData) return; ! if (NULL == pX11IMData->statusWindow) return; ! ! if ((int)value){ ! pX11IMData->statusWindow->on = True; ! }else{ ! pX11IMData->statusWindow->on = False; ! } ! return; }
< prev index next >