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
|