< prev index next >

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

Print this page




  35 
  36 #include <stdio.h>
  37 #include <stdlib.h>
  38 #include <sys/time.h>
  39 #include <X11/keysym.h>
  40 #include <X11/Xlib.h>
  41 
  42 #define THROW_OUT_OF_MEMORY_ERROR() \
  43         JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL)
  44 
  45 struct X11InputMethodIDs {
  46   jfieldID pData;
  47 } x11InputMethodIDs;
  48 
  49 static int PreeditStartCallback(XIC, XPointer, XPointer);
  50 static void PreeditDoneCallback(XIC, XPointer, XPointer);
  51 static void PreeditDrawCallback(XIC, XPointer,
  52                                 XIMPreeditDrawCallbackStruct *);
  53 static void PreeditCaretCallback(XIC, XPointer,
  54                                  XIMPreeditCaretCallbackStruct *);
  55 #if defined(__linux__) || defined(MACOSX)
  56 static void StatusStartCallback(XIC, XPointer, XPointer);
  57 static void StatusDoneCallback(XIC, XPointer, XPointer);
  58 static void StatusDrawCallback(XIC, XPointer,
  59                                XIMStatusDrawCallbackStruct *);
  60 #endif
  61 
  62 #define ROOT_WINDOW_STYLES      (XIMPreeditNothing | XIMStatusNothing)
  63 #define NO_STYLES               (XIMPreeditNone | XIMStatusNone)
  64 
  65 #define PreeditStartIndex       0
  66 #define PreeditDoneIndex        1
  67 #define PreeditDrawIndex        2
  68 #define PreeditCaretIndex       3
  69 #if defined(__linux__) || defined(MACOSX)
  70 #define StatusStartIndex        4
  71 #define StatusDoneIndex         5
  72 #define StatusDrawIndex         6
  73 #define NCALLBACKS              7
  74 #else
  75 #define NCALLBACKS              4
  76 #endif
  77 
  78 /*
  79  * Callback function pointers: the order has to match the *Index
  80  * values above.
  81  */
  82 static XIMProc callback_funcs[NCALLBACKS] = {
  83     (XIMProc)(void *)&PreeditStartCallback,
  84     (XIMProc)PreeditDoneCallback,
  85     (XIMProc)PreeditDrawCallback,
  86     (XIMProc)PreeditCaretCallback,
  87 #if defined(__linux__) || defined(MACOSX)
  88     (XIMProc)StatusStartCallback,
  89     (XIMProc)StatusDoneCallback,
  90     (XIMProc)StatusDrawCallback,
  91 #endif
  92 };
  93 
  94 #if defined(__linux__) || defined(MACOSX)
  95 #define MAX_STATUS_LEN  100
  96 typedef struct {
  97     Window   w;                /*status window id        */
  98     Window   root;             /*the root window id      */
  99     Window   parent;           /*parent shell window     */
 100     int      x, y;             /*parent's upperleft position */
 101     int      width, height;    /*parent's width, height  */
 102     GC       lightGC;          /*gc for light border     */
 103     GC       dimGC;            /*gc for dim border       */
 104     GC       bgGC;             /*normal painting         */
 105     GC       fgGC;             /*normal painting         */
 106     int      statusW, statusH; /*status window's w, h    */
 107     int      rootW, rootH;     /*root window's w, h    */
 108     int      bWidth;           /*border width            */
 109     char     status[MAX_STATUS_LEN]; /*status text       */
 110     XFontSet fontset;           /*fontset for drawing    */
 111     int      off_x, off_y;
 112     Bool     on;                /*if the status window on*/
 113 } StatusWindow;
 114 #endif
 115 
 116 /*
 117  * X11InputMethodData keeps per X11InputMethod instance information. A pointer
 118  * to this data structure is kept in an X11InputMethod object (pData).
 119  */
 120 typedef struct _X11InputMethodData {
 121     XIC         current_ic;     /* current X Input Context */
 122     XIC         ic_active;      /* X Input Context for active clients */
 123     XIC         ic_passive;     /* X Input Context for passive clients */
 124     XIMCallback *callbacks;     /* callback parameters */
 125     jobject     x11inputmethod; /* global ref to X11InputMethod instance */
 126                                 /* associated with the XIC */
 127 #if defined(__linux__) || defined(MACOSX)
 128     StatusWindow *statusWindow; /* our own status window  */
 129 #endif
 130     char        *lookup_buf;    /* buffer used for XmbLookupString */
 131     int         lookup_buf_len; /* lookup buffer size in bytes */
 132 } X11InputMethodData;
 133 
 134 /*
 135  * When XIC is created, a global reference is created for
 136  * sun.awt.X11InputMethod object so that it could be used by the XIM callback
 137  * functions. This could be a dangerous thing to do when the original
 138  * X11InputMethod object is garbage collected and as a result,
 139  * destroyX11InputMethodData is called to delete the global reference.
 140  * If any XIM callback function still holds and uses the "already deleted"
 141  * global reference, disaster is going to happen. So we have to maintain
 142  * a list for these global references which is consulted first when the
 143  * callback functions or any function tries to use "currentX11InputMethodObject"
 144  * which always refers to the global reference try to use it.
 145  *
 146  */
 147 typedef struct _X11InputMethodGRefNode {


 158 
 159 Window  currentFocusWindow = 0;  /* current window that has focus for input
 160                                        method. (the best place to put this
 161                                        information should be
 162                                        currentX11InputMethodInstance's pData) */
 163 static XIM X11im = NULL;
 164 Display * dpy = NULL;
 165 
 166 #define GetJNIEnv() (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2)
 167 
 168 static void DestroyXIMCallback(XIM, XPointer, XPointer);
 169 static void OpenXIMCallback(Display *, XPointer, XPointer);
 170 /* Solaris XIM Extention */
 171 #define XNCommitStringCallback "commitStringCallback"
 172 static void CommitStringCallback(XIC, XPointer, XPointer);
 173 
 174 static X11InputMethodData * getX11InputMethodData(JNIEnv *, jobject);
 175 static void setX11InputMethodData(JNIEnv *, jobject, X11InputMethodData *);
 176 static void destroyX11InputMethodData(JNIEnv *, X11InputMethodData *);
 177 static void freeX11InputMethodData(JNIEnv *, X11InputMethodData *);
 178 #if defined(__linux__) || defined(MACOSX)
 179 static Window getParentWindow(Window);
 180 #endif
 181 
 182 #ifdef __solaris__
 183 /* Prototype for this function is missing in Solaris X11R6 Xlib.h */
 184 extern char *XSetIMValues(
 185 #if NeedVarargsPrototypes
 186     XIM /* im */, ...
 187 #endif
 188 );
 189 #endif
 190 
 191 /*
 192  * This function is stolen from /src/solaris/hpi/src/system_md.c
 193  * It is used in setting the time in Java-level InputEvents
 194  */
 195 jlong
 196 awt_util_nowMillisUTC()
 197 {
 198     struct timeval t;


 358 
 359     if (pX11IMData->ic_active != (XIC)0) {
 360         XUnsetICFocus(pX11IMData->ic_active);
 361         XDestroyIC(pX11IMData->ic_active);
 362         if (pX11IMData->ic_active != pX11IMData->ic_passive) {
 363             if (pX11IMData->ic_passive != (XIC)0) {
 364                 XUnsetICFocus(pX11IMData->ic_passive);
 365                 XDestroyIC(pX11IMData->ic_passive);
 366             }
 367             pX11IMData->ic_passive = (XIC)0;
 368             pX11IMData->current_ic = (XIC)0;
 369         }
 370     }
 371 
 372     freeX11InputMethodData(env, pX11IMData);
 373 }
 374 
 375 static void
 376 freeX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData)
 377 {
 378 #if defined(__linux__) || defined(MACOSX)
 379     if (pX11IMData->statusWindow != NULL){
 380         StatusWindow *sw = pX11IMData->statusWindow;
 381         XFreeGC(awt_display, sw->lightGC);
 382         XFreeGC(awt_display, sw->dimGC);
 383         XFreeGC(awt_display, sw->bgGC);
 384         XFreeGC(awt_display, sw->fgGC);
 385         if (sw->fontset != NULL) {
 386             XFreeFontSet(awt_display, sw->fontset);
 387         }
 388         XDestroyWindow(awt_display, sw->w);
 389         free((void*)sw);
 390     }
 391 #endif
 392 
 393     if (pX11IMData->callbacks)
 394         free((void *)pX11IMData->callbacks);
 395 
 396     if (env) {
 397         /* Remove the global reference from the list, so that
 398            the callback function or whoever refers to it could know.


 461     KeySym keysym = NoSymbol;
 462     Status status;
 463     int mblen;
 464     jstring javastr;
 465     XIC ic;
 466     Boolean result = True;
 467     static Boolean composing = False;
 468 
 469     /*
 470       printf("lookupString: entering...\n");
 471      */
 472 
 473     if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) {
 474         currentX11InputMethodInstance = NULL;
 475         return False;
 476     }
 477 
 478     pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance);
 479 
 480     if (pX11IMData == NULL) {
 481 #if defined(__linux__) || defined(MACOSX)
 482         return False;
 483 #else
 484         return result;
 485 #endif
 486     }
 487 
 488     if ((ic = pX11IMData->current_ic) == (XIC)0){
 489 #if defined(__linux__) || defined(MACOSX)
 490         return False;
 491 #else
 492         return result;
 493 #endif
 494     }
 495 
 496     /* allocate the lookup buffer at the first invocation */
 497     if (pX11IMData->lookup_buf_len == 0) {
 498         pX11IMData->lookup_buf = (char *)malloc(INITIAL_LOOKUP_BUF_SIZE);
 499         if (pX11IMData->lookup_buf == NULL) {
 500             THROW_OUT_OF_MEMORY_ERROR();
 501             return result;
 502         }
 503         pX11IMData->lookup_buf_len = INITIAL_LOOKUP_BUF_SIZE;
 504     }
 505 
 506     mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf,
 507                             pX11IMData->lookup_buf_len - 1, &keysym, &status);
 508 
 509     /*


 561         */
 562         if (keysym == XK_Multi_key)
 563             composing = True;
 564         if (! composing) {
 565             *keysymp = keysym;
 566             result = False;
 567         }
 568         break;
 569 
 570     case XLookupNone:
 571         /*
 572         printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n",
 573                event->type, event->state, event->keycode, keysym);
 574         */
 575         break;
 576     }
 577 
 578     return result;
 579 }
 580 
 581 #if defined(__linux__) || defined(MACOSX)
 582 static StatusWindow *createStatusWindow(Window parent) {
 583     StatusWindow *statusWindow;
 584     XSetWindowAttributes attrib;
 585     unsigned long attribmask;
 586     Window containerWindow;
 587     Window status;
 588     Window child;
 589     XWindowAttributes xwa;
 590     XWindowAttributes xxwa;
 591     /* Variable for XCreateFontSet()*/
 592     char **mclr;
 593     int  mccr = 0;
 594     char *dsr;
 595     unsigned long bg, fg, light, dim;
 596     int x, y, off_x, off_y, xx, yy;
 597     unsigned int w, h, bw, depth;
 598     XGCValues values;
 599     unsigned long valuemask = 0;  /*ignore XGCvalue and use defaults*/
 600     int screen = 0;
 601     int i;


 835             || statusWindow->height != xwa.height){
 836           statusWindow->x = x;
 837           statusWindow->y = y;
 838           statusWindow->height = xwa.height;
 839 
 840           x = statusWindow->x - statusWindow->off_x;
 841           y = statusWindow->y + statusWindow->height - statusWindow->off_y;
 842           if (x < 0 ) {
 843               x = 0;
 844           }
 845           if (x + statusWindow->statusW > statusWindow->rootW){
 846               x = statusWindow->rootW - statusWindow->statusW;
 847           }
 848           if (y + statusWindow->statusH > statusWindow->rootH){
 849               y = statusWindow->rootH - statusWindow->statusH;
 850           }
 851           XMoveWindow(dpy, statusWindow->w, x, y);
 852         }
 853     }
 854 }
 855 #endif  /* __linux__ || MACOSX */
 856 
 857 /*
 858  * Creates two XICs, one for active clients and the other for passive
 859  * clients. All information on those XICs are stored in the
 860  * X11InputMethodData given by the pX11IMData parameter.
 861  *
 862  * For active clients: Try to use preedit callback to support
 863  * on-the-spot. If tc is not null, the XIC to be created will
 864  * share the Status Area with Motif widgets (TextComponents). If the
 865  * preferable styles can't be used, fallback to root-window styles. If
 866  * root-window styles failed, fallback to None styles.
 867  *
 868  * For passive clients: Try to use root-window styles. If failed,
 869  * fallback to None styles.
 870  */
 871 static Bool
 872 createXIC(JNIEnv * env, X11InputMethodData *pX11IMData, Window w)
 873 {
 874     XVaNestedList preedit = NULL;
 875     XVaNestedList status = NULL;


 881     unsigned short i;
 882     XIMStyles *im_styles;
 883     char *ret = NULL;
 884 
 885     if (X11im == NULL) {
 886         return False;
 887     }
 888     if (!w) {
 889         return False;
 890     }
 891 
 892     ret = XGetIMValues(X11im, XNQueryInputStyle, &im_styles, NULL);
 893 
 894     if (ret != NULL) {
 895         jio_fprintf(stderr,"XGetIMValues: %s\n",ret);
 896         return FALSE ;
 897     }
 898 
 899     on_the_spot_styles |= XIMStatusNothing;
 900 
 901 #if defined(__linux__) || defined(MACOSX)
 902     /*kinput does not support XIMPreeditCallbacks and XIMStatusArea
 903       at the same time, so use StatusCallback to draw the status
 904       ourself
 905     */
 906     for (i = 0; i < im_styles->count_styles; i++) {
 907         if (im_styles->supported_styles[i] == (XIMPreeditCallbacks | XIMStatusCallbacks)) {
 908             on_the_spot_styles = (XIMPreeditCallbacks | XIMStatusCallbacks);
 909             break;
 910         }
 911     }
 912 #endif /* __linux__ || MACOSX */
 913 
 914     for (i = 0; i < im_styles->count_styles; i++) {
 915         active_styles |= im_styles->supported_styles[i] & on_the_spot_styles;
 916         passive_styles |= im_styles->supported_styles[i] & ROOT_WINDOW_STYLES;
 917         no_styles |= im_styles->supported_styles[i] & NO_STYLES;
 918     }
 919 
 920     XFree(im_styles);
 921 
 922     if (active_styles != on_the_spot_styles) {
 923         if (passive_styles == ROOT_WINDOW_STYLES)
 924             active_styles = passive_styles;
 925         else {
 926             if (no_styles == NO_STYLES)
 927                 active_styles = passive_styles = NO_STYLES;
 928             else
 929                 active_styles = passive_styles = 0;
 930         }
 931     } else {
 932         if (passive_styles != ROOT_WINDOW_STYLES) {


 946 
 947         callbacks = (XIMCallback *)malloc(sizeof(XIMCallback) * NCALLBACKS);
 948         if (callbacks == (XIMCallback *)NULL)
 949             return False;
 950         pX11IMData->callbacks = callbacks;
 951 
 952         for (i = 0; i < NCALLBACKS; i++, callbacks++) {
 953             callbacks->client_data = (XPointer) pX11IMData->x11inputmethod;
 954             callbacks->callback = callback_funcs[i];
 955         }
 956 
 957         callbacks = pX11IMData->callbacks;
 958         preedit = (XVaNestedList)XVaCreateNestedList(0,
 959                         XNPreeditStartCallback, &callbacks[PreeditStartIndex],
 960                         XNPreeditDoneCallback,  &callbacks[PreeditDoneIndex],
 961                         XNPreeditDrawCallback,  &callbacks[PreeditDrawIndex],
 962                         XNPreeditCaretCallback, &callbacks[PreeditCaretIndex],
 963                         NULL);
 964         if (preedit == (XVaNestedList)NULL)
 965             goto err;
 966 #if defined(__linux__) || defined(MACOSX)
 967         /*always try XIMStatusCallbacks for active client...*/
 968         {
 969             status = (XVaNestedList)XVaCreateNestedList(0,
 970                         XNStatusStartCallback, &callbacks[StatusStartIndex],
 971                         XNStatusDoneCallback,  &callbacks[StatusDoneIndex],
 972                         XNStatusDrawCallback, &callbacks[StatusDrawIndex],
 973                         NULL);
 974 
 975             if (status == NULL)
 976                 goto err;
 977             pX11IMData->statusWindow = createStatusWindow(w);
 978             pX11IMData->ic_active = XCreateIC(X11im,
 979                                               XNClientWindow, w,
 980                                               XNFocusWindow, w,
 981                                               XNInputStyle, active_styles,
 982                                               XNPreeditAttributes, preedit,
 983                                               XNStatusAttributes, status,
 984                                               NULL);
 985             XFree((void *)status);
 986             XFree((void *)preedit);
 987         }
 988 #else /* !__linux__ && !MACOSX */
 989         pX11IMData->ic_active = XCreateIC(X11im,
 990                                           XNClientWindow, w,
 991                                           XNFocusWindow, w,
 992                                           XNInputStyle, active_styles,
 993                                           XNPreeditAttributes, preedit,
 994                                           NULL);
 995         XFree((void *)preedit);
 996 #endif /* __linux__ || MACOSX */
 997     } else {
 998         pX11IMData->ic_active = XCreateIC(X11im,
 999                                           XNClientWindow, w,
1000                                           XNFocusWindow, w,
1001                                           XNInputStyle, active_styles,
1002                                           NULL);
1003         pX11IMData->ic_passive = pX11IMData->ic_active;
1004     }
1005 
1006     if (pX11IMData->ic_active == (XIC)0
1007         || pX11IMData->ic_passive == (XIC)0) {
1008         return False;
1009     }
1010 
1011     /*
1012      * Use commit string call back if possible.
1013      * This will ensure the correct order of preedit text and commit text
1014      */
1015     {
1016         XIMCallback cb;


1156                          "(Ljava/lang/String;[IIIIJ)V",
1157                          javastr,
1158                          style,
1159                          (jint)pre_draw->chg_first,
1160                          (jint)pre_draw->chg_length,
1161                          (jint)pre_draw->caret,
1162                          awt_util_nowMillisUTC());
1163 finally:
1164     AWT_UNLOCK();
1165     return;
1166 }
1167 
1168 static void
1169 PreeditCaretCallback(XIC ic, XPointer client_data,
1170                      XIMPreeditCaretCallbackStruct *pre_caret)
1171 {
1172     /*ARGSUSED*/
1173     /* printf("Native: PreeditCaretCallback\n"); */
1174 }
1175 
1176 #if defined(__linux__) || defined(MACOSX)
1177 static void
1178 StatusStartCallback(XIC ic, XPointer client_data, XPointer call_data)
1179 {
1180     /*ARGSUSED*/
1181     /*printf("StatusStartCallback:\n");  */
1182 }
1183 
1184 static void
1185 StatusDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
1186 {
1187     /*ARGSUSED*/
1188     /*printf("StatusDoneCallback:\n"); */
1189     JNIEnv *env = GetJNIEnv();
1190     X11InputMethodData *pX11IMData = NULL;
1191     StatusWindow *statusWindow;
1192 
1193     AWT_LOCK();
1194 
1195     if (!isX11InputMethodGRefInList((jobject)client_data)) {
1196         if ((jobject)client_data == currentX11InputMethodInstance) {


1245             } else {
1246                 char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
1247                 strncpy(statusWindow->status, mbstr, MAX_STATUS_LEN);
1248                 statusWindow->status[MAX_STATUS_LEN - 1] = '\0';
1249             }
1250             statusWindow->on = True;
1251             onoffStatusWindow(pX11IMData, statusWindow->parent, True);
1252             paintStatusWindow(statusWindow);
1253         } else {
1254             statusWindow->on = False;
1255             /*just turnoff the status window
1256             paintStatusWindow(statusWindow);
1257             */
1258             onoffStatusWindow(pX11IMData, 0, False);
1259         }
1260     }
1261 
1262  finally:
1263     AWT_UNLOCK();
1264 }
1265 #endif /* __linux__ || MACOSX */
1266 
1267 static void CommitStringCallback(XIC ic, XPointer client_data, XPointer call_data) {
1268     JNIEnv *env = GetJNIEnv();
1269     XIMText * text = (XIMText *)call_data;
1270     X11InputMethodData *pX11IMData = NULL;
1271     jstring javastr;
1272 
1273     AWT_LOCK();
1274 
1275     if (!isX11InputMethodGRefInList((jobject)client_data)) {
1276         if ((jobject)client_data == currentX11InputMethodInstance) {
1277             currentX11InputMethodInstance = NULL;
1278         }
1279         goto finally;
1280     }
1281 
1282     if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) {
1283         goto finally;
1284     }
1285     currentX11InputMethodInstance = (jobject)client_data;


1339             }
1340         }
1341     }
1342     AWT_UNLOCK();
1343 }
1344 
1345 JNIEXPORT jboolean JNICALL
1346 Java_sun_awt_X11_XInputMethod_openXIMNative(JNIEnv *env,
1347                                             jobject this,
1348                                             jlong display)
1349 {
1350     Bool registered;
1351 
1352     AWT_LOCK();
1353 
1354     dpy = (Display *)jlong_to_ptr(display);
1355 
1356 /* Use IMInstantiate call back only on Linux, as there is a bug in Solaris
1357    (4768335)
1358 */
1359 #if defined(__linux__) || defined(MACOSX)
1360     registered = XRegisterIMInstantiateCallback(dpy, NULL, NULL,
1361                      NULL, (XIDProc)OpenXIMCallback, NULL);
1362     if (!registered) {
1363         /* directly call openXIM callback */
1364 #endif
1365         OpenXIMCallback(dpy, NULL, NULL);
1366 #if defined(__linux__) || defined(MACOSX)
1367     }
1368 #endif
1369 
1370     AWT_UNLOCK();
1371 
1372     return JNI_TRUE;
1373 }
1374 
1375 JNIEXPORT jboolean JNICALL
1376 Java_sun_awt_X11_XInputMethod_createXICNative(JNIEnv *env,
1377                                               jobject this,
1378                                               jlong window)
1379 {
1380     X11InputMethodData *pX11IMData;
1381     jobject globalRef;
1382     XIC ic;
1383 
1384     AWT_LOCK();
1385 
1386     if (!window) {
1387         JNU_ThrowNullPointerException(env, "NullPointerException");
1388         AWT_UNLOCK();
1389         return JNI_FALSE;
1390     }
1391 
1392     pX11IMData = (X11InputMethodData *) calloc(1, sizeof(X11InputMethodData));
1393     if (pX11IMData == NULL) {
1394         THROW_OUT_OF_MEMORY_ERROR();
1395         AWT_UNLOCK();
1396         return JNI_FALSE;
1397     }
1398 
1399     globalRef = (*env)->NewGlobalRef(env, this);
1400     pX11IMData->x11inputmethod = globalRef;
1401 #if defined(__linux__) || defined(MACOSX)
1402     pX11IMData->statusWindow = NULL;
1403 #endif /* __linux__ || MACOSX */
1404 
1405     pX11IMData->lookup_buf = 0;
1406     pX11IMData->lookup_buf_len = 0;
1407 
1408     if (createXIC(env, pX11IMData, (Window)window) == False) {
1409         destroyX11InputMethodData((JNIEnv *) NULL, pX11IMData);
1410         pX11IMData = (X11InputMethodData *) NULL;
1411         if ((*env)->ExceptionCheck(env)) {
1412             goto finally;
1413         }
1414     }
1415 
1416     setX11InputMethodData(env, this, pX11IMData);
1417 
1418 finally:
1419     AWT_UNLOCK();
1420     return (pX11IMData != NULL);
1421 }
1422 
1423 JNIEXPORT void JNICALL


1433     if (pX11IMData == NULL) {
1434         AWT_UNLOCK();
1435         return;
1436     }
1437 
1438     if (req) {
1439         if (!w) {
1440             AWT_UNLOCK();
1441             return;
1442         }
1443         pX11IMData->current_ic = active ?
1444                         pX11IMData->ic_active : pX11IMData->ic_passive;
1445         /*
1446          * On Solaris2.6, setXICWindowFocus() has to be invoked
1447          * before setting focus.
1448          */
1449         setXICWindowFocus(pX11IMData->current_ic, w);
1450         setXICFocus(pX11IMData->current_ic, req);
1451         currentX11InputMethodInstance = pX11IMData->x11inputmethod;
1452         currentFocusWindow =  w;
1453 #if defined(__linux__) || defined(MACOSX)
1454         if (active && pX11IMData->statusWindow && pX11IMData->statusWindow->on)
1455             onoffStatusWindow(pX11IMData, w, True);
1456 #endif
1457     } else {
1458         currentX11InputMethodInstance = NULL;
1459         currentFocusWindow = 0;
1460 #if defined(__linux__) || defined(MACOSX)
1461         onoffStatusWindow(pX11IMData, 0, False);
1462         if (pX11IMData->current_ic != NULL)
1463 #endif
1464         setXICFocus(pX11IMData->current_ic, req);
1465 
1466         pX11IMData->current_ic = (XIC)0;
1467     }
1468 
1469     XFlush(dpy);
1470     AWT_UNLOCK();
1471 }
1472 
1473 /*
1474  * Class:     sun_awt_X11InputMethodBase
1475  * Method:    initIDs
1476  * Signature: ()V
1477  * This function gets called from the static initializer for
1478  * X11InputMethod.java to initialize the fieldIDs for fields
1479  * that may be accessed from C
1480  */
1481 JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_initIDs
1482   (JNIEnv *env, jclass cls)
1483 {
1484     x11InputMethodIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J");
1485 }
1486 
1487 /*
1488  * Class:     sun_awt_X11InputMethodBase
1489  * Method:    turnoffStatusWindow
1490  * Signature: ()V
1491  */
1492 JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_turnoffStatusWindow
1493   (JNIEnv *env, jobject this)
1494 {
1495 #if defined(__linux__) || defined(MACOSX)
1496     X11InputMethodData *pX11IMData;
1497     StatusWindow *statusWindow;
1498 
1499     AWT_LOCK();
1500 
1501     if (NULL == currentX11InputMethodInstance
1502         || !isX11InputMethodGRefInList(currentX11InputMethodInstance)
1503         || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))
1504         || NULL == (statusWindow = pX11IMData->statusWindow)
1505         || !statusWindow->on ){
1506         AWT_UNLOCK();
1507         return;
1508     }
1509     onoffStatusWindow(pX11IMData, 0, False);
1510 
1511     AWT_UNLOCK();
1512 #endif
1513 }
1514 
1515 /*


1590 
1591 /*
1592  * Class:     sun_awt_X11InputMethodBase
1593  * Method:    setCompositionEnabledNative
1594  * Signature: (Z)Z
1595  *
1596  * This method tries to set the XNPreeditState attribute associated with the current
1597  * XIC to the passed in 'enable' state.
1598  *
1599  * Return JNI_TRUE if XNPreeditState attribute is successfully changed to the
1600  * 'enable' state; Otherwise, if XSetICValues fails to set this attribute,
1601  * java.lang.UnsupportedOperationException will be thrown. JNI_FALSE is returned if this
1602  * method fails due to other reasons.
1603  */
1604 JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_setCompositionEnabledNative
1605   (JNIEnv *env, jobject this, jboolean enable)
1606 {
1607     X11InputMethodData *pX11IMData;
1608     char * ret = NULL;
1609     XVaNestedList   pr_atrb;
1610 #if defined(__linux__) || defined(MACOSX)
1611     Boolean calledXSetICFocus = False;
1612 #endif
1613 
1614     AWT_LOCK();
1615     pX11IMData = getX11InputMethodData(env, this);
1616 
1617     if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) {
1618         AWT_UNLOCK();
1619         return JNI_FALSE;
1620     }
1621 
1622 #if defined(__linux__) || defined(MACOSX)
1623     if (NULL != pX11IMData->statusWindow) {
1624         Window focus = 0;
1625         int revert_to;
1626 #if defined(_LP64) && !defined(_LITTLE_ENDIAN)
1627         // The Window value which is used for XGetICValues must be 32bit on BigEndian XOrg's xlib
1628         unsigned int w = 0;
1629 #else
1630         Window w = 0;
1631 #endif
1632         XGetInputFocus(awt_display, &focus, &revert_to);
1633         XGetICValues(pX11IMData->current_ic, XNFocusWindow, &w, NULL);
1634         if (RevertToPointerRoot == revert_to
1635                 && pX11IMData->ic_active != pX11IMData->ic_passive) {
1636             if (pX11IMData->current_ic == pX11IMData->ic_active) {
1637                 if (getParentWindow(focus) == getParentWindow(w)) {
1638                     XUnsetICFocus(pX11IMData->ic_active);
1639                     calledXSetICFocus = True;
1640                 }
1641             }
1642         }
1643     }
1644 #endif
1645     pr_atrb = XVaCreateNestedList(0,
1646                   XNPreeditState, (enable ? XIMPreeditEnable : XIMPreeditDisable),
1647                   NULL);
1648     ret = XSetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL);
1649     XFree((void *)pr_atrb);
1650 #if defined(__linux__) || defined(MACOSX)
1651     if (calledXSetICFocus) {
1652         XSetICFocus(pX11IMData->ic_active);
1653     }
1654 #endif
1655     AWT_UNLOCK();
1656 
1657     if ((ret != 0)
1658             && ((strcmp(ret, XNPreeditAttributes) == 0)
1659             || (strcmp(ret, XNPreeditState) == 0))) {
1660         JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");
1661     }
1662 
1663     return (jboolean)(ret == 0);
1664 }
1665 
1666 /*
1667  * Class:     sun_awt_X11InputMethodBase
1668  * Method:    isCompositionEnabledNative
1669  * Signature: ()Z
1670  *


1697     }
1698 
1699     pr_atrb = XVaCreateNestedList(0, XNPreeditState, &state, NULL);
1700     ret = XGetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL);
1701     XFree((void *)pr_atrb);
1702     AWT_UNLOCK();
1703 
1704     if ((ret != 0)
1705             && ((strcmp(ret, XNPreeditAttributes) == 0)
1706             || (strcmp(ret, XNPreeditState) == 0))) {
1707         JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");
1708         return JNI_FALSE;
1709     }
1710 
1711     return (jboolean)(state == XIMPreeditEnable);
1712 }
1713 
1714 JNIEXPORT void JNICALL Java_sun_awt_X11_XInputMethod_adjustStatusWindow
1715   (JNIEnv *env, jobject this, jlong window)
1716 {
1717 #if defined(__linux__) || defined(MACOSX)
1718     AWT_LOCK();
1719     adjustStatusWindow(window);
1720     AWT_UNLOCK();
1721 #endif
1722 }
1723 
1724 #if defined(__linux__) || defined(MACOSX)
1725 static Window getParentWindow(Window w)
1726 {
1727     Window root=None, parent=None, *ignore_children=NULL;
1728     unsigned int ignore_uint=0;
1729     Status status = 0;
1730 
1731     if (w == None)
1732         return None;
1733     status = XQueryTree(dpy, w, &root, &parent, &ignore_children, &ignore_uint);
1734     XFree(ignore_children);
1735     if (status == 0)
1736         return None;
1737     return parent;
1738 }
1739 #endif


  35 
  36 #include <stdio.h>
  37 #include <stdlib.h>
  38 #include <sys/time.h>
  39 #include <X11/keysym.h>
  40 #include <X11/Xlib.h>
  41 
  42 #define THROW_OUT_OF_MEMORY_ERROR() \
  43         JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL)
  44 
  45 struct X11InputMethodIDs {
  46   jfieldID pData;
  47 } x11InputMethodIDs;
  48 
  49 static int PreeditStartCallback(XIC, XPointer, XPointer);
  50 static void PreeditDoneCallback(XIC, XPointer, XPointer);
  51 static void PreeditDrawCallback(XIC, XPointer,
  52                                 XIMPreeditDrawCallbackStruct *);
  53 static void PreeditCaretCallback(XIC, XPointer,
  54                                  XIMPreeditCaretCallbackStruct *);
  55 #if defined(__linux__)
  56 static void StatusStartCallback(XIC, XPointer, XPointer);
  57 static void StatusDoneCallback(XIC, XPointer, XPointer);
  58 static void StatusDrawCallback(XIC, XPointer,
  59                                XIMStatusDrawCallbackStruct *);
  60 #endif
  61 
  62 #define ROOT_WINDOW_STYLES      (XIMPreeditNothing | XIMStatusNothing)
  63 #define NO_STYLES               (XIMPreeditNone | XIMStatusNone)
  64 
  65 #define PreeditStartIndex       0
  66 #define PreeditDoneIndex        1
  67 #define PreeditDrawIndex        2
  68 #define PreeditCaretIndex       3
  69 #if defined(__linux__)
  70 #define StatusStartIndex        4
  71 #define StatusDoneIndex         5
  72 #define StatusDrawIndex         6
  73 #define NCALLBACKS              7
  74 #else
  75 #define NCALLBACKS              4
  76 #endif
  77 
  78 /*
  79  * Callback function pointers: the order has to match the *Index
  80  * values above.
  81  */
  82 static XIMProc callback_funcs[NCALLBACKS] = {
  83     (XIMProc)(void *)&PreeditStartCallback,
  84     (XIMProc)PreeditDoneCallback,
  85     (XIMProc)PreeditDrawCallback,
  86     (XIMProc)PreeditCaretCallback,
  87 #if defined(__linux__)
  88     (XIMProc)StatusStartCallback,
  89     (XIMProc)StatusDoneCallback,
  90     (XIMProc)StatusDrawCallback,
  91 #endif
  92 };
  93 
  94 #if defined(__linux__)
  95 #define MAX_STATUS_LEN  100
  96 typedef struct {
  97     Window   w;                /*status window id        */
  98     Window   root;             /*the root window id      */
  99     Window   parent;           /*parent shell window     */
 100     int      x, y;             /*parent's upperleft position */
 101     int      width, height;    /*parent's width, height  */
 102     GC       lightGC;          /*gc for light border     */
 103     GC       dimGC;            /*gc for dim border       */
 104     GC       bgGC;             /*normal painting         */
 105     GC       fgGC;             /*normal painting         */
 106     int      statusW, statusH; /*status window's w, h    */
 107     int      rootW, rootH;     /*root window's w, h    */
 108     int      bWidth;           /*border width            */
 109     char     status[MAX_STATUS_LEN]; /*status text       */
 110     XFontSet fontset;           /*fontset for drawing    */
 111     int      off_x, off_y;
 112     Bool     on;                /*if the status window on*/
 113 } StatusWindow;
 114 #endif
 115 
 116 /*
 117  * X11InputMethodData keeps per X11InputMethod instance information. A pointer
 118  * to this data structure is kept in an X11InputMethod object (pData).
 119  */
 120 typedef struct _X11InputMethodData {
 121     XIC         current_ic;     /* current X Input Context */
 122     XIC         ic_active;      /* X Input Context for active clients */
 123     XIC         ic_passive;     /* X Input Context for passive clients */
 124     XIMCallback *callbacks;     /* callback parameters */
 125     jobject     x11inputmethod; /* global ref to X11InputMethod instance */
 126                                 /* associated with the XIC */
 127 #if defined(__linux__)
 128     StatusWindow *statusWindow; /* our own status window  */
 129 #endif
 130     char        *lookup_buf;    /* buffer used for XmbLookupString */
 131     int         lookup_buf_len; /* lookup buffer size in bytes */
 132 } X11InputMethodData;
 133 
 134 /*
 135  * When XIC is created, a global reference is created for
 136  * sun.awt.X11InputMethod object so that it could be used by the XIM callback
 137  * functions. This could be a dangerous thing to do when the original
 138  * X11InputMethod object is garbage collected and as a result,
 139  * destroyX11InputMethodData is called to delete the global reference.
 140  * If any XIM callback function still holds and uses the "already deleted"
 141  * global reference, disaster is going to happen. So we have to maintain
 142  * a list for these global references which is consulted first when the
 143  * callback functions or any function tries to use "currentX11InputMethodObject"
 144  * which always refers to the global reference try to use it.
 145  *
 146  */
 147 typedef struct _X11InputMethodGRefNode {


 158 
 159 Window  currentFocusWindow = 0;  /* current window that has focus for input
 160                                        method. (the best place to put this
 161                                        information should be
 162                                        currentX11InputMethodInstance's pData) */
 163 static XIM X11im = NULL;
 164 Display * dpy = NULL;
 165 
 166 #define GetJNIEnv() (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2)
 167 
 168 static void DestroyXIMCallback(XIM, XPointer, XPointer);
 169 static void OpenXIMCallback(Display *, XPointer, XPointer);
 170 /* Solaris XIM Extention */
 171 #define XNCommitStringCallback "commitStringCallback"
 172 static void CommitStringCallback(XIC, XPointer, XPointer);
 173 
 174 static X11InputMethodData * getX11InputMethodData(JNIEnv *, jobject);
 175 static void setX11InputMethodData(JNIEnv *, jobject, X11InputMethodData *);
 176 static void destroyX11InputMethodData(JNIEnv *, X11InputMethodData *);
 177 static void freeX11InputMethodData(JNIEnv *, X11InputMethodData *);
 178 #if defined(__linux__)
 179 static Window getParentWindow(Window);
 180 #endif
 181 
 182 #ifdef __solaris__
 183 /* Prototype for this function is missing in Solaris X11R6 Xlib.h */
 184 extern char *XSetIMValues(
 185 #if NeedVarargsPrototypes
 186     XIM /* im */, ...
 187 #endif
 188 );
 189 #endif
 190 
 191 /*
 192  * This function is stolen from /src/solaris/hpi/src/system_md.c
 193  * It is used in setting the time in Java-level InputEvents
 194  */
 195 jlong
 196 awt_util_nowMillisUTC()
 197 {
 198     struct timeval t;


 358 
 359     if (pX11IMData->ic_active != (XIC)0) {
 360         XUnsetICFocus(pX11IMData->ic_active);
 361         XDestroyIC(pX11IMData->ic_active);
 362         if (pX11IMData->ic_active != pX11IMData->ic_passive) {
 363             if (pX11IMData->ic_passive != (XIC)0) {
 364                 XUnsetICFocus(pX11IMData->ic_passive);
 365                 XDestroyIC(pX11IMData->ic_passive);
 366             }
 367             pX11IMData->ic_passive = (XIC)0;
 368             pX11IMData->current_ic = (XIC)0;
 369         }
 370     }
 371 
 372     freeX11InputMethodData(env, pX11IMData);
 373 }
 374 
 375 static void
 376 freeX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData)
 377 {
 378 #if defined(__linux__)
 379     if (pX11IMData->statusWindow != NULL){
 380         StatusWindow *sw = pX11IMData->statusWindow;
 381         XFreeGC(awt_display, sw->lightGC);
 382         XFreeGC(awt_display, sw->dimGC);
 383         XFreeGC(awt_display, sw->bgGC);
 384         XFreeGC(awt_display, sw->fgGC);
 385         if (sw->fontset != NULL) {
 386             XFreeFontSet(awt_display, sw->fontset);
 387         }
 388         XDestroyWindow(awt_display, sw->w);
 389         free((void*)sw);
 390     }
 391 #endif
 392 
 393     if (pX11IMData->callbacks)
 394         free((void *)pX11IMData->callbacks);
 395 
 396     if (env) {
 397         /* Remove the global reference from the list, so that
 398            the callback function or whoever refers to it could know.


 461     KeySym keysym = NoSymbol;
 462     Status status;
 463     int mblen;
 464     jstring javastr;
 465     XIC ic;
 466     Boolean result = True;
 467     static Boolean composing = False;
 468 
 469     /*
 470       printf("lookupString: entering...\n");
 471      */
 472 
 473     if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) {
 474         currentX11InputMethodInstance = NULL;
 475         return False;
 476     }
 477 
 478     pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance);
 479 
 480     if (pX11IMData == NULL) {
 481 #if defined(__linux__)
 482         return False;
 483 #else
 484         return result;
 485 #endif
 486     }
 487 
 488     if ((ic = pX11IMData->current_ic) == (XIC)0){
 489 #if defined(__linux__)
 490         return False;
 491 #else
 492         return result;
 493 #endif
 494     }
 495 
 496     /* allocate the lookup buffer at the first invocation */
 497     if (pX11IMData->lookup_buf_len == 0) {
 498         pX11IMData->lookup_buf = (char *)malloc(INITIAL_LOOKUP_BUF_SIZE);
 499         if (pX11IMData->lookup_buf == NULL) {
 500             THROW_OUT_OF_MEMORY_ERROR();
 501             return result;
 502         }
 503         pX11IMData->lookup_buf_len = INITIAL_LOOKUP_BUF_SIZE;
 504     }
 505 
 506     mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf,
 507                             pX11IMData->lookup_buf_len - 1, &keysym, &status);
 508 
 509     /*


 561         */
 562         if (keysym == XK_Multi_key)
 563             composing = True;
 564         if (! composing) {
 565             *keysymp = keysym;
 566             result = False;
 567         }
 568         break;
 569 
 570     case XLookupNone:
 571         /*
 572         printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n",
 573                event->type, event->state, event->keycode, keysym);
 574         */
 575         break;
 576     }
 577 
 578     return result;
 579 }
 580 
 581 #if defined(__linux__)
 582 static StatusWindow *createStatusWindow(Window parent) {
 583     StatusWindow *statusWindow;
 584     XSetWindowAttributes attrib;
 585     unsigned long attribmask;
 586     Window containerWindow;
 587     Window status;
 588     Window child;
 589     XWindowAttributes xwa;
 590     XWindowAttributes xxwa;
 591     /* Variable for XCreateFontSet()*/
 592     char **mclr;
 593     int  mccr = 0;
 594     char *dsr;
 595     unsigned long bg, fg, light, dim;
 596     int x, y, off_x, off_y, xx, yy;
 597     unsigned int w, h, bw, depth;
 598     XGCValues values;
 599     unsigned long valuemask = 0;  /*ignore XGCvalue and use defaults*/
 600     int screen = 0;
 601     int i;


 835             || statusWindow->height != xwa.height){
 836           statusWindow->x = x;
 837           statusWindow->y = y;
 838           statusWindow->height = xwa.height;
 839 
 840           x = statusWindow->x - statusWindow->off_x;
 841           y = statusWindow->y + statusWindow->height - statusWindow->off_y;
 842           if (x < 0 ) {
 843               x = 0;
 844           }
 845           if (x + statusWindow->statusW > statusWindow->rootW){
 846               x = statusWindow->rootW - statusWindow->statusW;
 847           }
 848           if (y + statusWindow->statusH > statusWindow->rootH){
 849               y = statusWindow->rootH - statusWindow->statusH;
 850           }
 851           XMoveWindow(dpy, statusWindow->w, x, y);
 852         }
 853     }
 854 }
 855 #endif  /* __linux__ */
 856 
 857 /*
 858  * Creates two XICs, one for active clients and the other for passive
 859  * clients. All information on those XICs are stored in the
 860  * X11InputMethodData given by the pX11IMData parameter.
 861  *
 862  * For active clients: Try to use preedit callback to support
 863  * on-the-spot. If tc is not null, the XIC to be created will
 864  * share the Status Area with Motif widgets (TextComponents). If the
 865  * preferable styles can't be used, fallback to root-window styles. If
 866  * root-window styles failed, fallback to None styles.
 867  *
 868  * For passive clients: Try to use root-window styles. If failed,
 869  * fallback to None styles.
 870  */
 871 static Bool
 872 createXIC(JNIEnv * env, X11InputMethodData *pX11IMData, Window w)
 873 {
 874     XVaNestedList preedit = NULL;
 875     XVaNestedList status = NULL;


 881     unsigned short i;
 882     XIMStyles *im_styles;
 883     char *ret = NULL;
 884 
 885     if (X11im == NULL) {
 886         return False;
 887     }
 888     if (!w) {
 889         return False;
 890     }
 891 
 892     ret = XGetIMValues(X11im, XNQueryInputStyle, &im_styles, NULL);
 893 
 894     if (ret != NULL) {
 895         jio_fprintf(stderr,"XGetIMValues: %s\n",ret);
 896         return FALSE ;
 897     }
 898 
 899     on_the_spot_styles |= XIMStatusNothing;
 900 
 901 #if defined(__linux__)
 902     /*kinput does not support XIMPreeditCallbacks and XIMStatusArea
 903       at the same time, so use StatusCallback to draw the status
 904       ourself
 905     */
 906     for (i = 0; i < im_styles->count_styles; i++) {
 907         if (im_styles->supported_styles[i] == (XIMPreeditCallbacks | XIMStatusCallbacks)) {
 908             on_the_spot_styles = (XIMPreeditCallbacks | XIMStatusCallbacks);
 909             break;
 910         }
 911     }
 912 #endif /* __linux__ */
 913 
 914     for (i = 0; i < im_styles->count_styles; i++) {
 915         active_styles |= im_styles->supported_styles[i] & on_the_spot_styles;
 916         passive_styles |= im_styles->supported_styles[i] & ROOT_WINDOW_STYLES;
 917         no_styles |= im_styles->supported_styles[i] & NO_STYLES;
 918     }
 919 
 920     XFree(im_styles);
 921 
 922     if (active_styles != on_the_spot_styles) {
 923         if (passive_styles == ROOT_WINDOW_STYLES)
 924             active_styles = passive_styles;
 925         else {
 926             if (no_styles == NO_STYLES)
 927                 active_styles = passive_styles = NO_STYLES;
 928             else
 929                 active_styles = passive_styles = 0;
 930         }
 931     } else {
 932         if (passive_styles != ROOT_WINDOW_STYLES) {


 946 
 947         callbacks = (XIMCallback *)malloc(sizeof(XIMCallback) * NCALLBACKS);
 948         if (callbacks == (XIMCallback *)NULL)
 949             return False;
 950         pX11IMData->callbacks = callbacks;
 951 
 952         for (i = 0; i < NCALLBACKS; i++, callbacks++) {
 953             callbacks->client_data = (XPointer) pX11IMData->x11inputmethod;
 954             callbacks->callback = callback_funcs[i];
 955         }
 956 
 957         callbacks = pX11IMData->callbacks;
 958         preedit = (XVaNestedList)XVaCreateNestedList(0,
 959                         XNPreeditStartCallback, &callbacks[PreeditStartIndex],
 960                         XNPreeditDoneCallback,  &callbacks[PreeditDoneIndex],
 961                         XNPreeditDrawCallback,  &callbacks[PreeditDrawIndex],
 962                         XNPreeditCaretCallback, &callbacks[PreeditCaretIndex],
 963                         NULL);
 964         if (preedit == (XVaNestedList)NULL)
 965             goto err;
 966 #if defined(__linux__)
 967         /*always try XIMStatusCallbacks for active client...*/
 968         {
 969             status = (XVaNestedList)XVaCreateNestedList(0,
 970                         XNStatusStartCallback, &callbacks[StatusStartIndex],
 971                         XNStatusDoneCallback,  &callbacks[StatusDoneIndex],
 972                         XNStatusDrawCallback, &callbacks[StatusDrawIndex],
 973                         NULL);
 974 
 975             if (status == NULL)
 976                 goto err;
 977             pX11IMData->statusWindow = createStatusWindow(w);
 978             pX11IMData->ic_active = XCreateIC(X11im,
 979                                               XNClientWindow, w,
 980                                               XNFocusWindow, w,
 981                                               XNInputStyle, active_styles,
 982                                               XNPreeditAttributes, preedit,
 983                                               XNStatusAttributes, status,
 984                                               NULL);
 985             XFree((void *)status);
 986             XFree((void *)preedit);
 987         }
 988 #else /* !__linux__ */
 989         pX11IMData->ic_active = XCreateIC(X11im,
 990                                           XNClientWindow, w,
 991                                           XNFocusWindow, w,
 992                                           XNInputStyle, active_styles,
 993                                           XNPreeditAttributes, preedit,
 994                                           NULL);
 995         XFree((void *)preedit);
 996 #endif /* __linux__ */
 997     } else {
 998         pX11IMData->ic_active = XCreateIC(X11im,
 999                                           XNClientWindow, w,
1000                                           XNFocusWindow, w,
1001                                           XNInputStyle, active_styles,
1002                                           NULL);
1003         pX11IMData->ic_passive = pX11IMData->ic_active;
1004     }
1005 
1006     if (pX11IMData->ic_active == (XIC)0
1007         || pX11IMData->ic_passive == (XIC)0) {
1008         return False;
1009     }
1010 
1011     /*
1012      * Use commit string call back if possible.
1013      * This will ensure the correct order of preedit text and commit text
1014      */
1015     {
1016         XIMCallback cb;


1156                          "(Ljava/lang/String;[IIIIJ)V",
1157                          javastr,
1158                          style,
1159                          (jint)pre_draw->chg_first,
1160                          (jint)pre_draw->chg_length,
1161                          (jint)pre_draw->caret,
1162                          awt_util_nowMillisUTC());
1163 finally:
1164     AWT_UNLOCK();
1165     return;
1166 }
1167 
1168 static void
1169 PreeditCaretCallback(XIC ic, XPointer client_data,
1170                      XIMPreeditCaretCallbackStruct *pre_caret)
1171 {
1172     /*ARGSUSED*/
1173     /* printf("Native: PreeditCaretCallback\n"); */
1174 }
1175 
1176 #if defined(__linux__)
1177 static void
1178 StatusStartCallback(XIC ic, XPointer client_data, XPointer call_data)
1179 {
1180     /*ARGSUSED*/
1181     /*printf("StatusStartCallback:\n");  */
1182 }
1183 
1184 static void
1185 StatusDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
1186 {
1187     /*ARGSUSED*/
1188     /*printf("StatusDoneCallback:\n"); */
1189     JNIEnv *env = GetJNIEnv();
1190     X11InputMethodData *pX11IMData = NULL;
1191     StatusWindow *statusWindow;
1192 
1193     AWT_LOCK();
1194 
1195     if (!isX11InputMethodGRefInList((jobject)client_data)) {
1196         if ((jobject)client_data == currentX11InputMethodInstance) {


1245             } else {
1246                 char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
1247                 strncpy(statusWindow->status, mbstr, MAX_STATUS_LEN);
1248                 statusWindow->status[MAX_STATUS_LEN - 1] = '\0';
1249             }
1250             statusWindow->on = True;
1251             onoffStatusWindow(pX11IMData, statusWindow->parent, True);
1252             paintStatusWindow(statusWindow);
1253         } else {
1254             statusWindow->on = False;
1255             /*just turnoff the status window
1256             paintStatusWindow(statusWindow);
1257             */
1258             onoffStatusWindow(pX11IMData, 0, False);
1259         }
1260     }
1261 
1262  finally:
1263     AWT_UNLOCK();
1264 }
1265 #endif /* __linux__ */
1266 
1267 static void CommitStringCallback(XIC ic, XPointer client_data, XPointer call_data) {
1268     JNIEnv *env = GetJNIEnv();
1269     XIMText * text = (XIMText *)call_data;
1270     X11InputMethodData *pX11IMData = NULL;
1271     jstring javastr;
1272 
1273     AWT_LOCK();
1274 
1275     if (!isX11InputMethodGRefInList((jobject)client_data)) {
1276         if ((jobject)client_data == currentX11InputMethodInstance) {
1277             currentX11InputMethodInstance = NULL;
1278         }
1279         goto finally;
1280     }
1281 
1282     if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) {
1283         goto finally;
1284     }
1285     currentX11InputMethodInstance = (jobject)client_data;


1339             }
1340         }
1341     }
1342     AWT_UNLOCK();
1343 }
1344 
1345 JNIEXPORT jboolean JNICALL
1346 Java_sun_awt_X11_XInputMethod_openXIMNative(JNIEnv *env,
1347                                             jobject this,
1348                                             jlong display)
1349 {
1350     Bool registered;
1351 
1352     AWT_LOCK();
1353 
1354     dpy = (Display *)jlong_to_ptr(display);
1355 
1356 /* Use IMInstantiate call back only on Linux, as there is a bug in Solaris
1357    (4768335)
1358 */
1359 #if defined(__linux__)
1360     registered = XRegisterIMInstantiateCallback(dpy, NULL, NULL,
1361                      NULL, (XIDProc)OpenXIMCallback, NULL);
1362     if (!registered) {
1363         /* directly call openXIM callback */
1364 #endif
1365         OpenXIMCallback(dpy, NULL, NULL);
1366 #if defined(__linux__)
1367     }
1368 #endif
1369 
1370     AWT_UNLOCK();
1371 
1372     return JNI_TRUE;
1373 }
1374 
1375 JNIEXPORT jboolean JNICALL
1376 Java_sun_awt_X11_XInputMethod_createXICNative(JNIEnv *env,
1377                                               jobject this,
1378                                               jlong window)
1379 {
1380     X11InputMethodData *pX11IMData;
1381     jobject globalRef;
1382     XIC ic;
1383 
1384     AWT_LOCK();
1385 
1386     if (!window) {
1387         JNU_ThrowNullPointerException(env, "NullPointerException");
1388         AWT_UNLOCK();
1389         return JNI_FALSE;
1390     }
1391 
1392     pX11IMData = (X11InputMethodData *) calloc(1, sizeof(X11InputMethodData));
1393     if (pX11IMData == NULL) {
1394         THROW_OUT_OF_MEMORY_ERROR();
1395         AWT_UNLOCK();
1396         return JNI_FALSE;
1397     }
1398 
1399     globalRef = (*env)->NewGlobalRef(env, this);
1400     pX11IMData->x11inputmethod = globalRef;
1401 #if defined(__linux__)
1402     pX11IMData->statusWindow = NULL;
1403 #endif /* __linux__ */
1404 
1405     pX11IMData->lookup_buf = 0;
1406     pX11IMData->lookup_buf_len = 0;
1407 
1408     if (createXIC(env, pX11IMData, (Window)window) == False) {
1409         destroyX11InputMethodData((JNIEnv *) NULL, pX11IMData);
1410         pX11IMData = (X11InputMethodData *) NULL;
1411         if ((*env)->ExceptionCheck(env)) {
1412             goto finally;
1413         }
1414     }
1415 
1416     setX11InputMethodData(env, this, pX11IMData);
1417 
1418 finally:
1419     AWT_UNLOCK();
1420     return (pX11IMData != NULL);
1421 }
1422 
1423 JNIEXPORT void JNICALL


1433     if (pX11IMData == NULL) {
1434         AWT_UNLOCK();
1435         return;
1436     }
1437 
1438     if (req) {
1439         if (!w) {
1440             AWT_UNLOCK();
1441             return;
1442         }
1443         pX11IMData->current_ic = active ?
1444                         pX11IMData->ic_active : pX11IMData->ic_passive;
1445         /*
1446          * On Solaris2.6, setXICWindowFocus() has to be invoked
1447          * before setting focus.
1448          */
1449         setXICWindowFocus(pX11IMData->current_ic, w);
1450         setXICFocus(pX11IMData->current_ic, req);
1451         currentX11InputMethodInstance = pX11IMData->x11inputmethod;
1452         currentFocusWindow =  w;
1453 #if defined(__linux__)
1454         if (active && pX11IMData->statusWindow && pX11IMData->statusWindow->on)
1455             onoffStatusWindow(pX11IMData, w, True);
1456 #endif
1457     } else {
1458         currentX11InputMethodInstance = NULL;
1459         currentFocusWindow = 0;
1460 #if defined(__linux__)
1461         onoffStatusWindow(pX11IMData, 0, False);
1462         if (pX11IMData->current_ic != NULL)
1463 #endif
1464         setXICFocus(pX11IMData->current_ic, req);
1465 
1466         pX11IMData->current_ic = (XIC)0;
1467     }
1468 
1469     XFlush(dpy);
1470     AWT_UNLOCK();
1471 }
1472 
1473 /*
1474  * Class:     sun_awt_X11InputMethodBase
1475  * Method:    initIDs
1476  * Signature: ()V
1477  * This function gets called from the static initializer for
1478  * X11InputMethod.java to initialize the fieldIDs for fields
1479  * that may be accessed from C
1480  */
1481 JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_initIDs
1482   (JNIEnv *env, jclass cls)
1483 {
1484     x11InputMethodIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J");
1485 }
1486 
1487 /*
1488  * Class:     sun_awt_X11InputMethodBase
1489  * Method:    turnoffStatusWindow
1490  * Signature: ()V
1491  */
1492 JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_turnoffStatusWindow
1493   (JNIEnv *env, jobject this)
1494 {
1495 #if defined(__linux__)
1496     X11InputMethodData *pX11IMData;
1497     StatusWindow *statusWindow;
1498 
1499     AWT_LOCK();
1500 
1501     if (NULL == currentX11InputMethodInstance
1502         || !isX11InputMethodGRefInList(currentX11InputMethodInstance)
1503         || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))
1504         || NULL == (statusWindow = pX11IMData->statusWindow)
1505         || !statusWindow->on ){
1506         AWT_UNLOCK();
1507         return;
1508     }
1509     onoffStatusWindow(pX11IMData, 0, False);
1510 
1511     AWT_UNLOCK();
1512 #endif
1513 }
1514 
1515 /*


1590 
1591 /*
1592  * Class:     sun_awt_X11InputMethodBase
1593  * Method:    setCompositionEnabledNative
1594  * Signature: (Z)Z
1595  *
1596  * This method tries to set the XNPreeditState attribute associated with the current
1597  * XIC to the passed in 'enable' state.
1598  *
1599  * Return JNI_TRUE if XNPreeditState attribute is successfully changed to the
1600  * 'enable' state; Otherwise, if XSetICValues fails to set this attribute,
1601  * java.lang.UnsupportedOperationException will be thrown. JNI_FALSE is returned if this
1602  * method fails due to other reasons.
1603  */
1604 JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_setCompositionEnabledNative
1605   (JNIEnv *env, jobject this, jboolean enable)
1606 {
1607     X11InputMethodData *pX11IMData;
1608     char * ret = NULL;
1609     XVaNestedList   pr_atrb;
1610 #if defined(__linux__)
1611     Boolean calledXSetICFocus = False;
1612 #endif
1613 
1614     AWT_LOCK();
1615     pX11IMData = getX11InputMethodData(env, this);
1616 
1617     if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) {
1618         AWT_UNLOCK();
1619         return JNI_FALSE;
1620     }
1621 
1622 #if defined(__linux__)
1623     if (NULL != pX11IMData->statusWindow) {
1624         Window focus = 0;
1625         int revert_to;
1626 #if defined(_LP64) && !defined(_LITTLE_ENDIAN)
1627         // The Window value which is used for XGetICValues must be 32bit on BigEndian XOrg's xlib
1628         unsigned int w = 0;
1629 #else
1630         Window w = 0;
1631 #endif
1632         XGetInputFocus(awt_display, &focus, &revert_to);
1633         XGetICValues(pX11IMData->current_ic, XNFocusWindow, &w, NULL);
1634         if (RevertToPointerRoot == revert_to
1635                 && pX11IMData->ic_active != pX11IMData->ic_passive) {
1636             if (pX11IMData->current_ic == pX11IMData->ic_active) {
1637                 if (getParentWindow(focus) == getParentWindow(w)) {
1638                     XUnsetICFocus(pX11IMData->ic_active);
1639                     calledXSetICFocus = True;
1640                 }
1641             }
1642         }
1643     }
1644 #endif
1645     pr_atrb = XVaCreateNestedList(0,
1646                   XNPreeditState, (enable ? XIMPreeditEnable : XIMPreeditDisable),
1647                   NULL);
1648     ret = XSetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL);
1649     XFree((void *)pr_atrb);
1650 #if defined(__linux__)
1651     if (calledXSetICFocus) {
1652         XSetICFocus(pX11IMData->ic_active);
1653     }
1654 #endif
1655     AWT_UNLOCK();
1656 
1657     if ((ret != 0)
1658             && ((strcmp(ret, XNPreeditAttributes) == 0)
1659             || (strcmp(ret, XNPreeditState) == 0))) {
1660         JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");
1661     }
1662 
1663     return (jboolean)(ret == 0);
1664 }
1665 
1666 /*
1667  * Class:     sun_awt_X11InputMethodBase
1668  * Method:    isCompositionEnabledNative
1669  * Signature: ()Z
1670  *


1697     }
1698 
1699     pr_atrb = XVaCreateNestedList(0, XNPreeditState, &state, NULL);
1700     ret = XGetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL);
1701     XFree((void *)pr_atrb);
1702     AWT_UNLOCK();
1703 
1704     if ((ret != 0)
1705             && ((strcmp(ret, XNPreeditAttributes) == 0)
1706             || (strcmp(ret, XNPreeditState) == 0))) {
1707         JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");
1708         return JNI_FALSE;
1709     }
1710 
1711     return (jboolean)(state == XIMPreeditEnable);
1712 }
1713 
1714 JNIEXPORT void JNICALL Java_sun_awt_X11_XInputMethod_adjustStatusWindow
1715   (JNIEnv *env, jobject this, jlong window)
1716 {
1717 #if defined(__linux__)
1718     AWT_LOCK();
1719     adjustStatusWindow(window);
1720     AWT_UNLOCK();
1721 #endif
1722 }
1723 
1724 #if defined(__linux__)
1725 static Window getParentWindow(Window w)
1726 {
1727     Window root=None, parent=None, *ignore_children=NULL;
1728     unsigned int ignore_uint=0;
1729     Status status = 0;
1730 
1731     if (w == None)
1732         return None;
1733     status = XQueryTree(dpy, w, &root, &parent, &ignore_children, &ignore_uint);
1734     XFree(ignore_children);
1735     if (status == 0)
1736         return None;
1737     return parent;
1738 }
1739 #endif
< prev index next >