Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/awt/awt_InputMethod.c
32287 views
1
/*
2
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
#ifdef HEADLESS
27
#error This file should not be included in headless library
28
#endif
29
30
#include <stdio.h>
31
#include <stdlib.h>
32
#include <X11/Xlib.h>
33
#include <X11/keysym.h>
34
#include <sys/time.h>
35
36
#include "awt.h"
37
#include "awt_p.h"
38
39
#include <sun_awt_X11InputMethod.h>
40
#include <sun_awt_X11_XInputMethod.h>
41
42
#define THROW_OUT_OF_MEMORY_ERROR() \
43
JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL)
44
#define SETARG(name, value) XtSetArg(args[argc], name, value); argc++
45
46
struct X11InputMethodIDs {
47
jfieldID pData;
48
} x11InputMethodIDs;
49
50
static void PreeditStartCallback(XIC, XPointer, XPointer);
51
static void PreeditDoneCallback(XIC, XPointer, XPointer);
52
static void PreeditDrawCallback(XIC, XPointer,
53
XIMPreeditDrawCallbackStruct *);
54
static void PreeditCaretCallback(XIC, XPointer,
55
XIMPreeditCaretCallbackStruct *);
56
#if defined(__linux__) || defined(MACOSX)
57
static void StatusStartCallback(XIC, XPointer, XPointer);
58
static void StatusDoneCallback(XIC, XPointer, XPointer);
59
static void StatusDrawCallback(XIC, XPointer,
60
XIMStatusDrawCallbackStruct *);
61
#endif
62
63
#define ROOT_WINDOW_STYLES (XIMPreeditNothing | XIMStatusNothing)
64
#define NO_STYLES (XIMPreeditNone | XIMStatusNone)
65
66
#define PreeditStartIndex 0
67
#define PreeditDoneIndex 1
68
#define PreeditDrawIndex 2
69
#define PreeditCaretIndex 3
70
#if defined(__linux__) || defined(MACOSX)
71
#define StatusStartIndex 4
72
#define StatusDoneIndex 5
73
#define StatusDrawIndex 6
74
#define NCALLBACKS 7
75
#else
76
#define NCALLBACKS 4
77
#endif
78
79
/*
80
* Callback function pointers: the order has to match the *Index
81
* values above.
82
*/
83
static XIMProc callback_funcs[NCALLBACKS] = {
84
(XIMProc)PreeditStartCallback,
85
(XIMProc)PreeditDoneCallback,
86
(XIMProc)PreeditDrawCallback,
87
(XIMProc)PreeditCaretCallback,
88
#if defined(__linux__) || defined(MACOSX)
89
(XIMProc)StatusStartCallback,
90
(XIMProc)StatusDoneCallback,
91
(XIMProc)StatusDrawCallback,
92
#endif
93
};
94
95
#if defined(__linux__) || defined(MACOSX)
96
#define MAX_STATUS_LEN 100
97
typedef struct {
98
Window w; /*status window id */
99
Window root; /*the root window id */
100
Window parent; /*parent shell window */
101
int x, y; /*parent's upperleft position */
102
int width, height; /*parent's width, height */
103
GC lightGC; /*gc for light border */
104
GC dimGC; /*gc for dim border */
105
GC bgGC; /*normal painting */
106
GC fgGC; /*normal painting */
107
int statusW, statusH; /*status window's w, h */
108
int rootW, rootH; /*root window's w, h */
109
int bWidth; /*border width */
110
char status[MAX_STATUS_LEN]; /*status text */
111
XFontSet fontset; /*fontset for drawing */
112
int off_x, off_y;
113
Bool on; /*if the status window on*/
114
} StatusWindow;
115
#endif
116
117
/*
118
* X11InputMethodData keeps per X11InputMethod instance information. A pointer
119
* to this data structure is kept in an X11InputMethod object (pData).
120
*/
121
typedef struct _X11InputMethodData {
122
XIC current_ic; /* current X Input Context */
123
XIC ic_active; /* X Input Context for active clients */
124
XIC ic_passive; /* X Input Context for passive clients */
125
XIMCallback *callbacks; /* callback parameters */
126
jobject x11inputmethod; /* global ref to X11InputMethod instance */
127
/* associated with the XIC */
128
#if defined(__linux__) || defined(MACOSX)
129
StatusWindow *statusWindow; /* our own status window */
130
#endif
131
char *lookup_buf; /* buffer used for XmbLookupString */
132
int lookup_buf_len; /* lookup buffer size in bytes */
133
} X11InputMethodData;
134
135
/*
136
* When XIC is created, a global reference is created for
137
* sun.awt.X11InputMethod object so that it could be used by the XIM callback
138
* functions. This could be a dangerous thing to do when the original
139
* X11InputMethod object is garbage collected and as a result,
140
* destroyX11InputMethodData is called to delete the global reference.
141
* If any XIM callback function still holds and uses the "already deleted"
142
* global reference, disaster is going to happen. So we have to maintain
143
* a list for these global references which is consulted first when the
144
* callback functions or any function tries to use "currentX11InputMethodObject"
145
* which always refers to the global reference try to use it.
146
*
147
*/
148
typedef struct _X11InputMethodGRefNode {
149
jobject inputMethodGRef;
150
struct _X11InputMethodGRefNode* next;
151
} X11InputMethodGRefNode;
152
153
X11InputMethodGRefNode *x11InputMethodGRefListHead = NULL;
154
155
/* reference to the current X11InputMethod instance, it is always
156
point to the global reference to the X11InputMethodObject since
157
it could be referenced by different threads. */
158
jobject currentX11InputMethodInstance = NULL;
159
160
Window currentFocusWindow = 0; /* current window that has focus for input
161
method. (the best place to put this
162
information should be
163
currentX11InputMethodInstance's pData) */
164
static XIM X11im = NULL;
165
Display * dpy = NULL;
166
167
#define GetJNIEnv() (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2)
168
169
static void DestroyXIMCallback(XIM, XPointer, XPointer);
170
static void OpenXIMCallback(Display *, XPointer, XPointer);
171
/* Solaris XIM Extention */
172
#define XNCommitStringCallback "commitStringCallback"
173
static void CommitStringCallback(XIC, XPointer, XPointer);
174
175
static X11InputMethodData * getX11InputMethodData(JNIEnv *, jobject);
176
static void setX11InputMethodData(JNIEnv *, jobject, X11InputMethodData *);
177
static void destroyX11InputMethodData(JNIEnv *, X11InputMethodData *);
178
static void freeX11InputMethodData(JNIEnv *, X11InputMethodData *);
179
180
#ifdef __solaris__
181
/* Prototype for this function is missing in Solaris X11R6 Xlib.h */
182
extern char *XSetIMValues(
183
#if NeedVarargsPrototypes
184
XIM /* im */, ...
185
#endif
186
);
187
#endif
188
189
/*
190
* This function is stolen from /src/solaris/hpi/src/system_md.c
191
* It is used in setting the time in Java-level InputEvents
192
*/
193
jlong
194
awt_util_nowMillisUTC()
195
{
196
struct timeval t;
197
gettimeofday(&t, NULL);
198
return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000);
199
}
200
201
/*
202
* Converts the wchar_t string to a multi-byte string calling wcstombs(). A
203
* buffer is allocated by malloc() to store the multi-byte string. NULL is
204
* returned if the given wchar_t string pointer is NULL or buffer allocation is
205
* failed.
206
*/
207
static char *
208
wcstombsdmp(wchar_t *wcs, int len)
209
{
210
size_t n;
211
char *mbs;
212
213
if (wcs == NULL)
214
return NULL;
215
216
n = len*MB_CUR_MAX + 1;
217
218
mbs = (char *) malloc(n * sizeof(char));
219
if (mbs == NULL) {
220
THROW_OUT_OF_MEMORY_ERROR();
221
return NULL;
222
}
223
224
/* TODO: check return values... Handle invalid characters properly... */
225
if (wcstombs(mbs, wcs, n) == (size_t)-1)
226
return NULL;
227
228
return mbs;
229
}
230
231
/*
232
* Returns True if the global reference is still in the list,
233
* otherwise False.
234
*/
235
static Bool isX11InputMethodGRefInList(jobject imGRef) {
236
X11InputMethodGRefNode *pX11InputMethodGRef = x11InputMethodGRefListHead;
237
238
if (imGRef == NULL) {
239
return False;
240
}
241
242
while (pX11InputMethodGRef != NULL) {
243
if (pX11InputMethodGRef->inputMethodGRef == imGRef) {
244
return True;
245
}
246
pX11InputMethodGRef = pX11InputMethodGRef->next;
247
}
248
249
return False;
250
}
251
252
/*
253
* Add the new created global reference to the list.
254
*/
255
static void addToX11InputMethodGRefList(jobject newX11InputMethodGRef) {
256
X11InputMethodGRefNode *newNode = NULL;
257
258
if (newX11InputMethodGRef == NULL ||
259
isX11InputMethodGRefInList(newX11InputMethodGRef)) {
260
return;
261
}
262
263
newNode = (X11InputMethodGRefNode *)malloc(sizeof(X11InputMethodGRefNode));
264
265
if (newNode == NULL) {
266
return;
267
} else {
268
newNode->inputMethodGRef = newX11InputMethodGRef;
269
newNode->next = x11InputMethodGRefListHead;
270
x11InputMethodGRefListHead = newNode;
271
}
272
}
273
274
/*
275
* Remove the global reference from the list.
276
*/
277
static void removeX11InputMethodGRefFromList(jobject x11InputMethodGRef) {
278
X11InputMethodGRefNode *pX11InputMethodGRef = NULL;
279
X11InputMethodGRefNode *cX11InputMethodGRef = x11InputMethodGRefListHead;
280
281
if (x11InputMethodGRefListHead == NULL ||
282
x11InputMethodGRef == NULL) {
283
return;
284
}
285
286
/* cX11InputMethodGRef always refers to the current node while
287
pX11InputMethodGRef refers to the previous node.
288
*/
289
while (cX11InputMethodGRef != NULL) {
290
if (cX11InputMethodGRef->inputMethodGRef == x11InputMethodGRef) {
291
break;
292
}
293
pX11InputMethodGRef = cX11InputMethodGRef;
294
cX11InputMethodGRef = cX11InputMethodGRef->next;
295
}
296
297
if (cX11InputMethodGRef == NULL) {
298
return; /* Not found. */
299
}
300
301
if (cX11InputMethodGRef == x11InputMethodGRefListHead) {
302
x11InputMethodGRefListHead = x11InputMethodGRefListHead->next;
303
} else {
304
pX11InputMethodGRef->next = cX11InputMethodGRef->next;
305
}
306
free(cX11InputMethodGRef);
307
308
return;
309
}
310
311
312
static X11InputMethodData * getX11InputMethodData(JNIEnv * env, jobject imInstance) {
313
X11InputMethodData *pX11IMData =
314
(X11InputMethodData *)JNU_GetLongFieldAsPtr(env, imInstance, x11InputMethodIDs.pData);
315
316
/*
317
* In case the XIM server was killed somehow, reset X11InputMethodData.
318
*/
319
if (X11im == NULL && pX11IMData != NULL) {
320
JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
321
"flushText",
322
"()V");
323
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
324
/* IMPORTANT:
325
The order of the following calls is critical since "imInstance" may
326
point to the global reference itself, if "freeX11InputMethodData" is called
327
first, the global reference will be destroyed and "setX11InputMethodData"
328
will in fact fail silently. So pX11IMData will not be set to NULL.
329
This could make the original java object refers to a deleted pX11IMData
330
object.
331
*/
332
setX11InputMethodData(env, imInstance, NULL);
333
freeX11InputMethodData(env, pX11IMData);
334
pX11IMData = NULL;
335
}
336
337
return pX11IMData;
338
}
339
340
static void setX11InputMethodData(JNIEnv * env, jobject imInstance, X11InputMethodData *pX11IMData) {
341
JNU_SetLongFieldFromPtr(env, imInstance, x11InputMethodIDs.pData, pX11IMData);
342
}
343
344
/* this function should be called within AWT_LOCK() */
345
static void
346
destroyX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData)
347
{
348
/*
349
* Destroy XICs
350
*/
351
if (pX11IMData == NULL) {
352
return;
353
}
354
355
if (pX11IMData->ic_active != (XIC)0) {
356
XUnsetICFocus(pX11IMData->ic_active);
357
XDestroyIC(pX11IMData->ic_active);
358
if (pX11IMData->ic_active != pX11IMData->ic_passive) {
359
if (pX11IMData->ic_passive != (XIC)0) {
360
XUnsetICFocus(pX11IMData->ic_passive);
361
XDestroyIC(pX11IMData->ic_passive);
362
}
363
pX11IMData->ic_passive = (XIC)0;
364
pX11IMData->current_ic = (XIC)0;
365
}
366
}
367
368
freeX11InputMethodData(env, pX11IMData);
369
}
370
371
static void
372
freeX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData)
373
{
374
#if defined(__linux__) || defined(MACOSX)
375
if (pX11IMData->statusWindow != NULL){
376
StatusWindow *sw = pX11IMData->statusWindow;
377
XFreeGC(awt_display, sw->lightGC);
378
XFreeGC(awt_display, sw->dimGC);
379
XFreeGC(awt_display, sw->bgGC);
380
XFreeGC(awt_display, sw->fgGC);
381
if (sw->fontset != NULL) {
382
XFreeFontSet(awt_display, sw->fontset);
383
}
384
XDestroyWindow(awt_display, sw->w);
385
free((void*)sw);
386
}
387
#endif
388
389
if (pX11IMData->callbacks)
390
free((void *)pX11IMData->callbacks);
391
392
if (env) {
393
/* Remove the global reference from the list, so that
394
the callback function or whoever refers to it could know.
395
*/
396
removeX11InputMethodGRefFromList(pX11IMData->x11inputmethod);
397
(*env)->DeleteGlobalRef(env, pX11IMData->x11inputmethod);
398
}
399
400
if (pX11IMData->lookup_buf) {
401
free((void *)pX11IMData->lookup_buf);
402
}
403
404
free((void *)pX11IMData);
405
}
406
407
/*
408
* Sets or unsets the focus to the given XIC.
409
*/
410
static void
411
setXICFocus(XIC ic, unsigned short req)
412
{
413
if (ic == NULL) {
414
(void)fprintf(stderr, "Couldn't find X Input Context\n");
415
return;
416
}
417
if (req == 1)
418
XSetICFocus(ic);
419
else
420
XUnsetICFocus(ic);
421
}
422
423
/*
424
* Sets the focus window to the given XIC.
425
*/
426
static void
427
setXICWindowFocus(XIC ic, Window w)
428
{
429
if (ic == NULL) {
430
(void)fprintf(stderr, "Couldn't find X Input Context\n");
431
return;
432
}
433
(void) XSetICValues(ic, XNFocusWindow, w, NULL);
434
}
435
436
/*
437
* Invokes XmbLookupString() to get something from the XIM. It invokes
438
* X11InputMethod.dispatchCommittedText() if XmbLookupString() returns
439
* committed text. This function is called from handleKeyEvent in canvas.c and
440
* it's under the Motif event loop thread context.
441
*
442
* Buffer usage: There is a bug in XFree86-4.3.0 XmbLookupString implementation,
443
* where it never returns XBufferOverflow. We need to allocate the initial lookup buffer
444
* big enough, so that the possibility that user encounters this problem is relatively
445
* small. When this bug gets fixed, we can make the initial buffer size smaller.
446
* Note that XmbLookupString() sometimes produces a non-null-terminated string.
447
*
448
* Returns True when there is a keysym value to be handled.
449
*/
450
#define INITIAL_LOOKUP_BUF_SIZE 512
451
452
Boolean
453
awt_x11inputmethod_lookupString(XKeyPressedEvent *event, KeySym *keysymp)
454
{
455
JNIEnv *env = GetJNIEnv();
456
X11InputMethodData *pX11IMData = NULL;
457
KeySym keysym = NoSymbol;
458
Status status;
459
int mblen;
460
jstring javastr;
461
XIC ic;
462
Boolean result = True;
463
static Boolean composing = False;
464
465
/*
466
printf("lookupString: entering...\n");
467
*/
468
469
if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) {
470
currentX11InputMethodInstance = NULL;
471
return False;
472
}
473
474
pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance);
475
476
if (pX11IMData == NULL) {
477
#if defined(__linux__) || defined(MACOSX)
478
return False;
479
#else
480
return result;
481
#endif
482
}
483
484
if ((ic = pX11IMData->current_ic) == (XIC)0){
485
#if defined(__linux__) || defined(MACOSX)
486
return False;
487
#else
488
return result;
489
#endif
490
}
491
492
/* allocate the lookup buffer at the first invocation */
493
if (pX11IMData->lookup_buf_len == 0) {
494
pX11IMData->lookup_buf = (char *)malloc(INITIAL_LOOKUP_BUF_SIZE);
495
if (pX11IMData->lookup_buf == NULL) {
496
THROW_OUT_OF_MEMORY_ERROR();
497
return result;
498
}
499
pX11IMData->lookup_buf_len = INITIAL_LOOKUP_BUF_SIZE;
500
}
501
502
mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf,
503
pX11IMData->lookup_buf_len - 1, &keysym, &status);
504
505
/*
506
* In case of overflow, a buffer is allocated and it retries
507
* XmbLookupString().
508
*/
509
if (status == XBufferOverflow) {
510
free((void *)pX11IMData->lookup_buf);
511
pX11IMData->lookup_buf_len = 0;
512
pX11IMData->lookup_buf = (char *)malloc(mblen + 1);
513
if (pX11IMData->lookup_buf == NULL) {
514
THROW_OUT_OF_MEMORY_ERROR();
515
return result;
516
}
517
pX11IMData->lookup_buf_len = mblen + 1;
518
mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf,
519
pX11IMData->lookup_buf_len - 1, &keysym, &status);
520
}
521
pX11IMData->lookup_buf[mblen] = 0;
522
523
/* Get keysym without taking modifiers into account first to map
524
* to AWT keyCode table.
525
*/
526
switch (status) {
527
case XLookupBoth:
528
if (!composing) {
529
if (event->keycode != 0) {
530
*keysymp = keysym;
531
result = False;
532
break;
533
}
534
}
535
composing = False;
536
/*FALLTHRU*/
537
case XLookupChars:
538
/*
539
printf("lookupString: status=XLookupChars, type=%d, state=%x, keycode=%x, keysym=%x\n",
540
event->type, event->state, event->keycode, keysym);
541
*/
542
javastr = JNU_NewStringPlatform(env, (const char *)pX11IMData->lookup_buf);
543
if (javastr != NULL) {
544
JNU_CallMethodByName(env, NULL,
545
currentX11InputMethodInstance,
546
"dispatchCommittedText",
547
"(Ljava/lang/String;J)V",
548
javastr,
549
event->time);
550
}
551
break;
552
553
case XLookupKeySym:
554
/*
555
printf("lookupString: status=XLookupKeySym, type=%d, state=%x, keycode=%x, keysym=%x\n",
556
event->type, event->state, event->keycode, keysym);
557
*/
558
if (keysym == XK_Multi_key)
559
composing = True;
560
if (! composing) {
561
*keysymp = keysym;
562
result = False;
563
}
564
break;
565
566
case XLookupNone:
567
/*
568
printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n",
569
event->type, event->state, event->keycode, keysym);
570
*/
571
break;
572
}
573
574
return result;
575
}
576
577
#if defined(__linux__) || defined(MACOSX)
578
static StatusWindow *createStatusWindow(
579
Window parent) {
580
StatusWindow *statusWindow;
581
XSetWindowAttributes attrib;
582
unsigned long attribmask;
583
Window containerWindow;
584
Window status;
585
Window child;
586
XWindowAttributes xwa;
587
XWindowAttributes xxwa;
588
/* Variable for XCreateFontSet()*/
589
char **mclr;
590
int mccr = 0;
591
char *dsr;
592
Pixel bg, fg, light, dim;
593
int x, y, off_x, off_y, xx, yy;
594
unsigned int w, h, bw, depth;
595
XGCValues values;
596
unsigned long valuemask = 0; /*ignore XGCvalue and use defaults*/
597
int screen = 0;
598
int i;
599
AwtGraphicsConfigDataPtr adata;
600
extern int awt_numScreens;
601
/*hardcode the size right now, should get the size base on font*/
602
int width=80, height=22;
603
Window rootWindow;
604
Window *ignoreWindowPtr;
605
unsigned int ignoreUnit;
606
607
XGetGeometry(dpy, parent, &rootWindow, &x, &y, &w, &h, &bw, &depth);
608
609
attrib.override_redirect = True;
610
attribmask = CWOverrideRedirect;
611
for (i = 0; i < awt_numScreens; i++) {
612
if (RootWindow(dpy, i) == rootWindow) {
613
screen = i;
614
break;
615
}
616
}
617
adata = getDefaultConfig(screen);
618
bg = adata->AwtColorMatch(255, 255, 255, adata);
619
fg = adata->AwtColorMatch(0, 0, 0, adata);
620
light = adata->AwtColorMatch(195, 195, 195, adata);
621
dim = adata->AwtColorMatch(128, 128, 128, adata);
622
623
XGetWindowAttributes(dpy, parent, &xwa);
624
bw = 2; /*xwa.border_width does not have the correct value*/
625
626
/*compare the size difference between parent container
627
and shell widget, the diff should be the border frame
628
and title bar height (?)*/
629
630
XQueryTree( dpy,
631
parent,
632
&rootWindow,
633
&containerWindow,
634
&ignoreWindowPtr,
635
&ignoreUnit);
636
XGetWindowAttributes(dpy, containerWindow, &xxwa);
637
638
off_x = (xxwa.width - xwa.width) / 2;
639
off_y = xxwa.height - xwa.height - off_x; /*it's magic:-) */
640
641
/*get the size of root window*/
642
XGetWindowAttributes(dpy, rootWindow, &xxwa);
643
644
XTranslateCoordinates(dpy,
645
parent, xwa.root,
646
xwa.x, xwa.y,
647
&x, &y,
648
&child);
649
xx = x - off_x;
650
yy = y + xwa.height - off_y;
651
if (xx < 0 ){
652
xx = 0;
653
}
654
if (xx + width > xxwa.width){
655
xx = xxwa.width - width;
656
}
657
if (yy + height > xxwa.height){
658
yy = xxwa.height - height;
659
}
660
661
status = XCreateWindow(dpy,
662
xwa.root,
663
xx, yy,
664
width, height,
665
0,
666
xwa.depth,
667
InputOutput,
668
adata->awt_visInfo.visual,
669
attribmask, &attrib);
670
XSelectInput(dpy, status,
671
ExposureMask | StructureNotifyMask | EnterWindowMask |
672
LeaveWindowMask | VisibilityChangeMask);
673
statusWindow = (StatusWindow*) calloc(1, sizeof(StatusWindow));
674
if (statusWindow == NULL){
675
THROW_OUT_OF_MEMORY_ERROR();
676
return NULL;
677
}
678
statusWindow->w = status;
679
//12-point font
680
statusWindow->fontset = XCreateFontSet(dpy,
681
"-*-*-medium-r-normal-*-*-120-*-*-*-*",
682
&mclr, &mccr, &dsr);
683
/* In case we didn't find the font set, release the list of missing characters */
684
if (mccr > 0) {
685
XFreeStringList(mclr);
686
}
687
statusWindow->parent = parent;
688
statusWindow->on = False;
689
statusWindow->x = x;
690
statusWindow->y = y;
691
statusWindow->width = xwa.width;
692
statusWindow->height = xwa.height;
693
statusWindow->off_x = off_x;
694
statusWindow->off_y = off_y;
695
statusWindow->bWidth = bw;
696
statusWindow->statusH = height;
697
statusWindow->statusW = width;
698
statusWindow->rootH = xxwa.height;
699
statusWindow->rootW = xxwa.width;
700
statusWindow->lightGC = XCreateGC(dpy, status, valuemask, &values);
701
XSetForeground(dpy, statusWindow->lightGC, light);
702
statusWindow->dimGC = XCreateGC(dpy, status, valuemask, &values);
703
XSetForeground(dpy, statusWindow->dimGC, dim);
704
statusWindow->fgGC = XCreateGC(dpy, status, valuemask, &values);
705
XSetForeground(dpy, statusWindow->fgGC, fg);
706
statusWindow->bgGC = XCreateGC(dpy, status, valuemask, &values);
707
XSetForeground(dpy, statusWindow->bgGC, bg);
708
return statusWindow;
709
}
710
711
/* This method is to turn off or turn on the status window. */
712
static void onoffStatusWindow(X11InputMethodData* pX11IMData,
713
Window parent,
714
Bool ON){
715
XWindowAttributes xwa;
716
Window child;
717
int x, y;
718
StatusWindow *statusWindow = NULL;
719
720
if (NULL == currentX11InputMethodInstance ||
721
NULL == pX11IMData ||
722
NULL == (statusWindow = pX11IMData->statusWindow)){
723
return;
724
}
725
726
if (ON == False){
727
XUnmapWindow(dpy, statusWindow->w);
728
statusWindow->on = False;
729
return;
730
}
731
parent = JNU_CallMethodByName(GetJNIEnv(), NULL, pX11IMData->x11inputmethod,
732
"getCurrentParentWindow",
733
"()J").j;
734
if (statusWindow->parent != parent){
735
statusWindow->parent = parent;
736
}
737
XGetWindowAttributes(dpy, parent, &xwa);
738
XTranslateCoordinates(dpy,
739
parent, xwa.root,
740
xwa.x, xwa.y,
741
&x, &y,
742
&child);
743
if (statusWindow->x != x
744
|| statusWindow->y != y
745
|| statusWindow->height != xwa.height){
746
statusWindow->x = x;
747
statusWindow->y = y;
748
statusWindow->height = xwa.height;
749
x = statusWindow->x - statusWindow->off_x;
750
y = statusWindow->y + statusWindow->height - statusWindow->off_y;
751
if (x < 0 ){
752
x = 0;
753
}
754
if (x + statusWindow->statusW > statusWindow->rootW){
755
x = statusWindow->rootW - statusWindow->statusW;
756
}
757
if (y + statusWindow->statusH > statusWindow->rootH){
758
y = statusWindow->rootH - statusWindow->statusH;
759
}
760
XMoveWindow(dpy, statusWindow->w, x, y);
761
}
762
statusWindow->on = True;
763
XMapWindow(dpy, statusWindow->w);
764
}
765
766
void paintStatusWindow(StatusWindow *statusWindow){
767
Window win = statusWindow->w;
768
GC lightgc = statusWindow->lightGC;
769
GC dimgc = statusWindow->dimGC;
770
GC bggc = statusWindow->bgGC;
771
GC fggc = statusWindow->fgGC;
772
773
int width = statusWindow->statusW;
774
int height = statusWindow->statusH;
775
int bwidth = statusWindow->bWidth;
776
XFillRectangle(dpy, win, bggc, 0, 0, width, height);
777
/* draw border */
778
XDrawLine(dpy, win, fggc, 0, 0, width, 0);
779
XDrawLine(dpy, win, fggc, 0, height-1, width-1, height-1);
780
XDrawLine(dpy, win, fggc, 0, 0, 0, height-1);
781
XDrawLine(dpy, win, fggc, width-1, 0, width-1, height-1);
782
783
XDrawLine(dpy, win, lightgc, 1, 1, width-bwidth, 1);
784
XDrawLine(dpy, win, lightgc, 1, 1, 1, height-2);
785
XDrawLine(dpy, win, lightgc, 1, height-2, width-bwidth, height-2);
786
XDrawLine(dpy, win, lightgc, width-bwidth-1, 1, width-bwidth-1, height-2);
787
788
XDrawLine(dpy, win, dimgc, 2, 2, 2, height-3);
789
XDrawLine(dpy, win, dimgc, 2, height-3, width-bwidth-1, height-3);
790
XDrawLine(dpy, win, dimgc, 2, 2, width-bwidth-2, 2);
791
XDrawLine(dpy, win, dimgc, width-bwidth, 2, width-bwidth, height-3);
792
if (statusWindow->fontset){
793
XmbDrawString(dpy, win, statusWindow->fontset, fggc,
794
bwidth + 2, height - bwidth - 4,
795
statusWindow->status,
796
strlen(statusWindow->status));
797
}
798
else{
799
/*too bad we failed to create a fontset for this locale*/
800
XDrawString(dpy, win, fggc, bwidth + 2, height - bwidth - 4,
801
"[InputMethod ON]", strlen("[InputMethod ON]"));
802
}
803
}
804
805
void statusWindowEventHandler(XEvent event){
806
JNIEnv *env = GetJNIEnv();
807
X11InputMethodData *pX11IMData = NULL;
808
StatusWindow *statusWindow;
809
810
if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) {
811
currentX11InputMethodInstance = NULL;
812
return;
813
}
814
815
if (NULL == currentX11InputMethodInstance
816
|| NULL == (pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance))
817
|| NULL == (statusWindow = pX11IMData->statusWindow)
818
|| statusWindow->w != event.xany.window){
819
return;
820
}
821
822
switch (event.type){
823
case Expose:
824
paintStatusWindow(statusWindow);
825
break;
826
case MapNotify:
827
case ConfigureNotify:
828
{
829
/*need to reset the stackMode...*/
830
XWindowChanges xwc;
831
int value_make = CWStackMode;
832
xwc.stack_mode = TopIf;
833
XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
834
}
835
break;
836
/*
837
case UnmapNotify:
838
case VisibilityNotify:
839
break;
840
*/
841
default:
842
break;
843
}
844
}
845
846
static void adjustStatusWindow(Window shell){
847
JNIEnv *env = GetJNIEnv();
848
X11InputMethodData *pX11IMData = NULL;
849
StatusWindow *statusWindow;
850
851
if (NULL == currentX11InputMethodInstance
852
|| !isX11InputMethodGRefInList(currentX11InputMethodInstance)
853
|| NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))
854
|| NULL == (statusWindow = pX11IMData->statusWindow)
855
|| !statusWindow->on) {
856
return;
857
}
858
{
859
XWindowAttributes xwa;
860
int x, y;
861
Window child;
862
XGetWindowAttributes(dpy, shell, &xwa);
863
XTranslateCoordinates(dpy,
864
shell, xwa.root,
865
xwa.x, xwa.y,
866
&x, &y,
867
&child);
868
if (statusWindow->x != x
869
|| statusWindow->y != y
870
|| statusWindow->height != xwa.height){
871
statusWindow->x = x;
872
statusWindow->y = y;
873
statusWindow->height = xwa.height;
874
875
x = statusWindow->x - statusWindow->off_x;
876
y = statusWindow->y + statusWindow->height - statusWindow->off_y;
877
if (x < 0 ){
878
x = 0;
879
}
880
if (x + statusWindow->statusW > statusWindow->rootW){
881
x = statusWindow->rootW - statusWindow->statusW;
882
}
883
if (y + statusWindow->statusH > statusWindow->rootH){
884
y = statusWindow->rootH - statusWindow->statusH;
885
}
886
XMoveWindow(dpy, statusWindow->w, x, y);
887
}
888
}
889
}
890
#endif /* __linux__ || MACOSX */
891
/*
892
* Creates two XICs, one for active clients and the other for passive
893
* clients. All information on those XICs are stored in the
894
* X11InputMethodData given by the pX11IMData parameter.
895
*
896
* For active clients: Try to use preedit callback to support
897
* on-the-spot. If tc is not null, the XIC to be created will
898
* share the Status Area with Motif widgets (TextComponents). If the
899
* preferable styles can't be used, fallback to root-window styles. If
900
* root-window styles failed, fallback to None styles.
901
*
902
* For passive clients: Try to use root-window styles. If failed,
903
* fallback to None styles.
904
*/
905
static Bool
906
createXIC(JNIEnv * env, X11InputMethodData *pX11IMData, Window w)
907
{
908
XVaNestedList preedit = NULL;
909
XVaNestedList status = NULL;
910
XIMStyle on_the_spot_styles = XIMPreeditCallbacks,
911
active_styles = 0,
912
passive_styles = 0,
913
no_styles = 0;
914
XIMCallback *callbacks;
915
unsigned short i;
916
XIMStyles *im_styles;
917
char *ret = NULL;
918
919
if (X11im == NULL) {
920
return False;
921
}
922
if (!w) {
923
return False;
924
}
925
926
ret = XGetIMValues(X11im, XNQueryInputStyle, &im_styles, NULL);
927
928
if (ret != NULL) {
929
jio_fprintf(stderr,"XGetIMValues: %s\n",ret);
930
return FALSE ;
931
}
932
933
#if defined(__linux__) || defined(MACOSX)
934
on_the_spot_styles |= XIMStatusNothing;
935
936
/*kinput does not support XIMPreeditCallbacks and XIMStatusArea
937
at the same time, so use StatusCallback to draw the status
938
ourself
939
*/
940
for (i = 0; i < im_styles->count_styles; i++) {
941
if (im_styles->supported_styles[i] == (XIMPreeditCallbacks | XIMStatusCallbacks)) {
942
on_the_spot_styles = (XIMPreeditCallbacks | XIMStatusCallbacks);
943
break;
944
}
945
}
946
#else /*! __linux__ && !MACOSX */
947
on_the_spot_styles |= XIMStatusNothing;
948
#endif /* __linux__ || MACOSX */
949
950
for (i = 0; i < im_styles->count_styles; i++) {
951
active_styles |= im_styles->supported_styles[i] & on_the_spot_styles;
952
passive_styles |= im_styles->supported_styles[i] & ROOT_WINDOW_STYLES;
953
no_styles |= im_styles->supported_styles[i] & NO_STYLES;
954
}
955
956
XFree(im_styles);
957
958
if (active_styles != on_the_spot_styles) {
959
if (passive_styles == ROOT_WINDOW_STYLES)
960
active_styles = passive_styles;
961
else {
962
if (no_styles == NO_STYLES)
963
active_styles = passive_styles = NO_STYLES;
964
else
965
active_styles = passive_styles = 0;
966
}
967
} else {
968
if (passive_styles != ROOT_WINDOW_STYLES) {
969
if (no_styles == NO_STYLES)
970
active_styles = passive_styles = NO_STYLES;
971
else
972
active_styles = passive_styles = 0;
973
}
974
}
975
976
if (active_styles == on_the_spot_styles) {
977
pX11IMData->ic_passive = XCreateIC(X11im,
978
XNClientWindow, w,
979
XNFocusWindow, w,
980
XNInputStyle, passive_styles,
981
NULL);
982
983
callbacks = (XIMCallback *)malloc(sizeof(XIMCallback) * NCALLBACKS);
984
if (callbacks == (XIMCallback *)NULL)
985
return False;
986
pX11IMData->callbacks = callbacks;
987
988
for (i = 0; i < NCALLBACKS; i++, callbacks++) {
989
callbacks->client_data = (XPointer) pX11IMData->x11inputmethod;
990
callbacks->callback = callback_funcs[i];
991
}
992
993
callbacks = pX11IMData->callbacks;
994
preedit = (XVaNestedList)XVaCreateNestedList(0,
995
XNPreeditStartCallback, &callbacks[PreeditStartIndex],
996
XNPreeditDoneCallback, &callbacks[PreeditDoneIndex],
997
XNPreeditDrawCallback, &callbacks[PreeditDrawIndex],
998
XNPreeditCaretCallback, &callbacks[PreeditCaretIndex],
999
NULL);
1000
if (preedit == (XVaNestedList)NULL)
1001
goto err;
1002
#if defined(__linux__) || defined(MACOSX)
1003
/*always try XIMStatusCallbacks for active client...*/
1004
{
1005
status = (XVaNestedList)XVaCreateNestedList(0,
1006
XNStatusStartCallback, &callbacks[StatusStartIndex],
1007
XNStatusDoneCallback, &callbacks[StatusDoneIndex],
1008
XNStatusDrawCallback, &callbacks[StatusDrawIndex],
1009
NULL);
1010
1011
if (status == NULL)
1012
goto err;
1013
pX11IMData->statusWindow = createStatusWindow(w);
1014
pX11IMData->ic_active = XCreateIC(X11im,
1015
XNClientWindow, w,
1016
XNFocusWindow, w,
1017
XNInputStyle, active_styles,
1018
XNPreeditAttributes, preedit,
1019
XNStatusAttributes, status,
1020
NULL);
1021
XFree((void *)status);
1022
XFree((void *)preedit);
1023
}
1024
#else /* !__linux__ && !MACOSX */
1025
pX11IMData->ic_active = XCreateIC(X11im,
1026
XNClientWindow, w,
1027
XNFocusWindow, w,
1028
XNInputStyle, active_styles,
1029
XNPreeditAttributes, preedit,
1030
NULL);
1031
XFree((void *)preedit);
1032
#endif /* __linux__ || MACOSX */
1033
} else {
1034
pX11IMData->ic_active = XCreateIC(X11im,
1035
XNClientWindow, w,
1036
XNFocusWindow, w,
1037
XNInputStyle, active_styles,
1038
NULL);
1039
pX11IMData->ic_passive = pX11IMData->ic_active;
1040
}
1041
1042
if (pX11IMData->ic_active == (XIC)0
1043
|| pX11IMData->ic_passive == (XIC)0) {
1044
return False;
1045
}
1046
1047
/*
1048
* Use commit string call back if possible.
1049
* This will ensure the correct order of preedit text and commit text
1050
*/
1051
{
1052
XIMCallback cb;
1053
cb.client_data = (XPointer) pX11IMData->x11inputmethod;
1054
cb.callback = (XIMProc) CommitStringCallback;
1055
XSetICValues (pX11IMData->ic_active, XNCommitStringCallback, &cb, NULL);
1056
if (pX11IMData->ic_active != pX11IMData->ic_passive) {
1057
XSetICValues (pX11IMData->ic_passive, XNCommitStringCallback, &cb, NULL);
1058
}
1059
}
1060
1061
/* Add the global reference object to X11InputMethod to the list. */
1062
addToX11InputMethodGRefList(pX11IMData->x11inputmethod);
1063
1064
return True;
1065
1066
err:
1067
if (preedit)
1068
XFree((void *)preedit);
1069
THROW_OUT_OF_MEMORY_ERROR();
1070
return False;
1071
}
1072
1073
static void
1074
PreeditStartCallback(XIC ic, XPointer client_data, XPointer call_data)
1075
{
1076
/*ARGSUSED*/
1077
/* printf("Native: PreeditCaretCallback\n"); */
1078
}
1079
1080
static void
1081
PreeditDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
1082
{
1083
/*ARGSUSED*/
1084
/* printf("Native: StatusStartCallback\n"); */
1085
}
1086
1087
/*
1088
* Translate the preedit draw callback items to Java values and invoke
1089
* X11InputMethod.dispatchComposedText().
1090
*
1091
* client_data: X11InputMethod object
1092
*/
1093
static void
1094
PreeditDrawCallback(XIC ic, XPointer client_data,
1095
XIMPreeditDrawCallbackStruct *pre_draw)
1096
{
1097
JNIEnv *env = GetJNIEnv();
1098
X11InputMethodData *pX11IMData = NULL;
1099
jmethodID x11imMethodID;
1100
1101
XIMText *text;
1102
jstring javastr = NULL;
1103
jintArray style = NULL;
1104
1105
/* printf("Native: PreeditDrawCallback() \n"); */
1106
if (pre_draw == NULL) {
1107
return;
1108
}
1109
AWT_LOCK();
1110
if (!isX11InputMethodGRefInList((jobject)client_data)) {
1111
if ((jobject)client_data == currentX11InputMethodInstance) {
1112
currentX11InputMethodInstance = NULL;
1113
}
1114
goto finally;
1115
}
1116
if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) {
1117
goto finally;
1118
}
1119
1120
if ((text = pre_draw->text) != NULL) {
1121
if (text->string.multi_byte != NULL) {
1122
if (pre_draw->text->encoding_is_wchar == False) {
1123
javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte);
1124
if (javastr == NULL) {
1125
goto finally;
1126
}
1127
} else {
1128
char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
1129
if (mbstr == NULL) {
1130
goto finally;
1131
}
1132
javastr = JNU_NewStringPlatform(env, (const char *)mbstr);
1133
free(mbstr);
1134
if (javastr == NULL) {
1135
goto finally;
1136
}
1137
}
1138
}
1139
if (text->feedback != NULL) {
1140
int cnt;
1141
jint *tmpstyle;
1142
1143
style = (*env)->NewIntArray(env, text->length);
1144
if (JNU_IsNull(env, style)) {
1145
(*env)->ExceptionClear(env);
1146
THROW_OUT_OF_MEMORY_ERROR();
1147
goto finally;
1148
}
1149
1150
if (sizeof(XIMFeedback) == sizeof(jint)) {
1151
/*
1152
* Optimization to avoid copying the array
1153
*/
1154
(*env)->SetIntArrayRegion(env, style, 0,
1155
text->length, (jint *)text->feedback);
1156
} else {
1157
tmpstyle = (jint *)malloc(sizeof(jint)*(text->length));
1158
if (tmpstyle == (jint *) NULL) {
1159
THROW_OUT_OF_MEMORY_ERROR();
1160
goto finally;
1161
}
1162
for (cnt = 0; cnt < (int)text->length; cnt++)
1163
tmpstyle[cnt] = text->feedback[cnt];
1164
(*env)->SetIntArrayRegion(env, style, 0,
1165
text->length, (jint *)tmpstyle);
1166
}
1167
}
1168
}
1169
JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
1170
"dispatchComposedText",
1171
"(Ljava/lang/String;[IIIIJ)V",
1172
javastr,
1173
style,
1174
(jint)pre_draw->chg_first,
1175
(jint)pre_draw->chg_length,
1176
(jint)pre_draw->caret,
1177
awt_util_nowMillisUTC());
1178
finally:
1179
AWT_UNLOCK();
1180
return;
1181
}
1182
1183
static void
1184
PreeditCaretCallback(XIC ic, XPointer client_data,
1185
XIMPreeditCaretCallbackStruct *pre_caret)
1186
{
1187
/*ARGSUSED*/
1188
/* printf("Native: PreeditCaretCallback\n"); */
1189
1190
}
1191
1192
#if defined(__linux__) || defined(MACOSX)
1193
static void
1194
StatusStartCallback(XIC ic, XPointer client_data, XPointer call_data)
1195
{
1196
/*ARGSUSED*/
1197
/*printf("StatusStartCallback:\n"); */
1198
1199
}
1200
1201
static void
1202
StatusDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
1203
{
1204
/*ARGSUSED*/
1205
/*printf("StatusDoneCallback:\n"); */
1206
1207
}
1208
1209
static void
1210
StatusDrawCallback(XIC ic, XPointer client_data,
1211
XIMStatusDrawCallbackStruct *status_draw)
1212
{
1213
/*ARGSUSED*/
1214
/*printf("StatusDrawCallback:\n"); */
1215
JNIEnv *env = GetJNIEnv();
1216
X11InputMethodData *pX11IMData = NULL;
1217
StatusWindow *statusWindow;
1218
1219
AWT_LOCK();
1220
1221
if (!isX11InputMethodGRefInList((jobject)client_data)) {
1222
if ((jobject)client_data == currentX11InputMethodInstance) {
1223
currentX11InputMethodInstance = NULL;
1224
}
1225
goto finally;
1226
}
1227
1228
if (NULL == (pX11IMData = getX11InputMethodData(env, (jobject)client_data))
1229
|| NULL == (statusWindow = pX11IMData->statusWindow)){
1230
goto finally;
1231
}
1232
currentX11InputMethodInstance = (jobject)client_data;
1233
1234
if (status_draw->type == XIMTextType){
1235
XIMText *text = (status_draw->data).text;
1236
if (text != NULL){
1237
if (text->string.multi_byte != NULL){
1238
strcpy(statusWindow->status, text->string.multi_byte);
1239
}
1240
else{
1241
char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
1242
strcpy(statusWindow->status, mbstr);
1243
}
1244
statusWindow->on = True;
1245
onoffStatusWindow(pX11IMData, statusWindow->parent, True);
1246
paintStatusWindow(statusWindow);
1247
}
1248
else {
1249
statusWindow->on = False;
1250
/*just turnoff the status window
1251
paintStatusWindow(statusWindow);
1252
*/
1253
onoffStatusWindow(pX11IMData, 0, False);
1254
}
1255
}
1256
1257
finally:
1258
AWT_UNLOCK();
1259
}
1260
#endif /* __linux__ || MACOSX */
1261
1262
static void CommitStringCallback(XIC ic, XPointer client_data, XPointer call_data) {
1263
JNIEnv *env = GetJNIEnv();
1264
XIMText * text = (XIMText *)call_data;
1265
X11InputMethodData *pX11IMData = NULL;
1266
jstring javastr;
1267
1268
AWT_LOCK();
1269
1270
if (!isX11InputMethodGRefInList((jobject)client_data)) {
1271
if ((jobject)client_data == currentX11InputMethodInstance) {
1272
currentX11InputMethodInstance = NULL;
1273
}
1274
goto finally;
1275
}
1276
1277
if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) {
1278
goto finally;
1279
}
1280
currentX11InputMethodInstance = (jobject)client_data;
1281
1282
if (text->encoding_is_wchar == False) {
1283
javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte);
1284
} else {
1285
char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
1286
if (mbstr == NULL) {
1287
goto finally;
1288
}
1289
javastr = JNU_NewStringPlatform(env, (const char *)mbstr);
1290
free(mbstr);
1291
}
1292
1293
if (javastr != NULL) {
1294
JNU_CallMethodByName(env, NULL,
1295
pX11IMData->x11inputmethod,
1296
"dispatchCommittedText",
1297
"(Ljava/lang/String;J)V",
1298
javastr,
1299
awt_util_nowMillisUTC());
1300
}
1301
finally:
1302
AWT_UNLOCK();
1303
}
1304
1305
static void OpenXIMCallback(Display *display, XPointer client_data, XPointer call_data) {
1306
XIMCallback ximCallback;
1307
1308
X11im = XOpenIM(display, NULL, NULL, NULL);
1309
if (X11im == NULL) {
1310
return;
1311
}
1312
1313
ximCallback.callback = (XIMProc)DestroyXIMCallback;
1314
ximCallback.client_data = NULL;
1315
XSetIMValues(X11im, XNDestroyCallback, &ximCallback, NULL);
1316
}
1317
1318
static void DestroyXIMCallback(XIM im, XPointer client_data, XPointer call_data) {
1319
/* mark that XIM server was destroyed */
1320
X11im = NULL;
1321
JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
1322
1323
AWT_LOCK();
1324
/* free the old pX11IMData and set it to null. this also avoids crashing
1325
* the jvm if the XIM server reappears */
1326
while (x11InputMethodGRefListHead != NULL) {
1327
getX11InputMethodData(env, x11InputMethodGRefListHead->inputMethodGRef);
1328
}
1329
AWT_UNLOCK();
1330
}
1331
1332
/*
1333
* Class: sun_awt_X11InputMethod
1334
* Method: initIDs
1335
* Signature: ()V
1336
*/
1337
1338
/* This function gets called from the static initializer for
1339
X11InputMethod.java
1340
to initialize the fieldIDs for fields that may be accessed from C */
1341
JNIEXPORT void JNICALL
1342
Java_sun_awt_X11InputMethod_initIDs(JNIEnv *env, jclass cls)
1343
{
1344
x11InputMethodIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J");
1345
}
1346
1347
1348
JNIEXPORT jboolean JNICALL
1349
Java_sun_awt_X11_XInputMethod_openXIMNative(JNIEnv *env,
1350
jobject this,
1351
jlong display)
1352
{
1353
Bool registered;
1354
1355
AWT_LOCK();
1356
1357
dpy = (Display *)jlong_to_ptr(display);
1358
1359
/* Use IMInstantiate call back only on Linux, as there is a bug in Solaris
1360
(4768335)
1361
*/
1362
#if defined(__linux__) || defined(MACOSX)
1363
registered = XRegisterIMInstantiateCallback(dpy, NULL, NULL,
1364
NULL, (XIDProc)OpenXIMCallback, NULL);
1365
if (!registered) {
1366
/* directly call openXIM callback */
1367
#endif
1368
OpenXIMCallback(dpy, NULL, NULL);
1369
#if defined(__linux__) || defined(MACOSX)
1370
}
1371
#endif
1372
1373
AWT_UNLOCK();
1374
1375
return JNI_TRUE;
1376
}
1377
1378
JNIEXPORT jboolean JNICALL
1379
Java_sun_awt_X11_XInputMethod_createXICNative(JNIEnv *env,
1380
jobject this,
1381
jlong window)
1382
{
1383
X11InputMethodData *pX11IMData;
1384
jobject globalRef;
1385
XIC ic;
1386
1387
AWT_LOCK();
1388
1389
if (!window) {
1390
JNU_ThrowNullPointerException(env, "NullPointerException");
1391
AWT_UNLOCK();
1392
return JNI_FALSE;
1393
}
1394
1395
pX11IMData = (X11InputMethodData *) calloc(1, sizeof(X11InputMethodData));
1396
if (pX11IMData == NULL) {
1397
THROW_OUT_OF_MEMORY_ERROR();
1398
AWT_UNLOCK();
1399
return JNI_FALSE;
1400
}
1401
1402
globalRef = (*env)->NewGlobalRef(env, this);
1403
pX11IMData->x11inputmethod = globalRef;
1404
#if defined(__linux__) || defined(MACOSX)
1405
pX11IMData->statusWindow = NULL;
1406
#endif /* __linux__ || MACOSX */
1407
1408
pX11IMData->lookup_buf = 0;
1409
pX11IMData->lookup_buf_len = 0;
1410
1411
if (createXIC(env, pX11IMData, (Window)window) == False) {
1412
destroyX11InputMethodData((JNIEnv *) NULL, pX11IMData);
1413
pX11IMData = (X11InputMethodData *) NULL;
1414
if ((*env)->ExceptionCheck(env)) {
1415
goto finally;
1416
}
1417
}
1418
1419
setX11InputMethodData(env, this, pX11IMData);
1420
1421
finally:
1422
AWT_UNLOCK();
1423
return (pX11IMData != NULL);
1424
}
1425
1426
JNIEXPORT void JNICALL
1427
Java_sun_awt_X11_XInputMethod_setXICFocusNative(JNIEnv *env,
1428
jobject this,
1429
jlong w,
1430
jboolean req,
1431
jboolean active)
1432
{
1433
X11InputMethodData *pX11IMData;
1434
AWT_LOCK();
1435
pX11IMData = getX11InputMethodData(env, this);
1436
if (pX11IMData == NULL) {
1437
AWT_UNLOCK();
1438
return;
1439
}
1440
1441
if (req) {
1442
if (!w) {
1443
AWT_UNLOCK();
1444
return;
1445
}
1446
pX11IMData->current_ic = active ?
1447
pX11IMData->ic_active : pX11IMData->ic_passive;
1448
/*
1449
* On Solaris2.6, setXICWindowFocus() has to be invoked
1450
* before setting focus.
1451
*/
1452
setXICWindowFocus(pX11IMData->current_ic, w);
1453
setXICFocus(pX11IMData->current_ic, req);
1454
currentX11InputMethodInstance = pX11IMData->x11inputmethod;
1455
currentFocusWindow = w;
1456
#if defined(__linux__) || defined(MACOSX)
1457
if (active && pX11IMData->statusWindow && pX11IMData->statusWindow->on)
1458
onoffStatusWindow(pX11IMData, w, True);
1459
#endif
1460
} else {
1461
currentX11InputMethodInstance = NULL;
1462
currentFocusWindow = 0;
1463
#if defined(__linux__) || defined(MACOSX)
1464
onoffStatusWindow(pX11IMData, 0, False);
1465
if (pX11IMData->current_ic != NULL)
1466
#endif
1467
setXICFocus(pX11IMData->current_ic, req);
1468
1469
pX11IMData->current_ic = (XIC)0;
1470
}
1471
1472
XFlush(dpy);
1473
AWT_UNLOCK();
1474
}
1475
1476
JNIEXPORT void JNICALL
1477
Java_sun_awt_X11InputMethod_turnoffStatusWindow(JNIEnv *env,
1478
jobject this)
1479
{
1480
#if defined(__linux__) || defined(MACOSX)
1481
X11InputMethodData *pX11IMData;
1482
StatusWindow *statusWindow;
1483
1484
AWT_LOCK();
1485
1486
if (NULL == currentX11InputMethodInstance
1487
|| !isX11InputMethodGRefInList(currentX11InputMethodInstance)
1488
|| NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))
1489
|| NULL == (statusWindow = pX11IMData->statusWindow)
1490
|| !statusWindow->on ){
1491
AWT_UNLOCK();
1492
return;
1493
}
1494
onoffStatusWindow(pX11IMData, 0, False);
1495
1496
AWT_UNLOCK();
1497
#endif
1498
}
1499
1500
JNIEXPORT void JNICALL
1501
Java_sun_awt_X11InputMethod_disposeXIC(JNIEnv *env,
1502
jobject this)
1503
{
1504
X11InputMethodData *pX11IMData = NULL;
1505
1506
AWT_LOCK();
1507
pX11IMData = getX11InputMethodData(env, this);
1508
if (pX11IMData == NULL) {
1509
AWT_UNLOCK();
1510
return;
1511
}
1512
1513
setX11InputMethodData(env, this, NULL);
1514
1515
if (pX11IMData->x11inputmethod == currentX11InputMethodInstance) {
1516
currentX11InputMethodInstance = NULL;
1517
currentFocusWindow = 0;
1518
}
1519
destroyX11InputMethodData(env, pX11IMData);
1520
AWT_UNLOCK();
1521
}
1522
1523
JNIEXPORT jstring JNICALL
1524
Java_sun_awt_X11InputMethod_resetXIC(JNIEnv *env,
1525
jobject this)
1526
{
1527
X11InputMethodData *pX11IMData;
1528
char *xText = NULL;
1529
jstring jText = (jstring)0;
1530
1531
AWT_LOCK();
1532
pX11IMData = getX11InputMethodData(env, this);
1533
if (pX11IMData == NULL) {
1534
AWT_UNLOCK();
1535
return jText;
1536
}
1537
1538
if (pX11IMData->current_ic)
1539
xText = XmbResetIC(pX11IMData->current_ic);
1540
else {
1541
/*
1542
* If there is no reference to the current XIC, try to reset both XICs.
1543
*/
1544
xText = XmbResetIC(pX11IMData->ic_active);
1545
/*it may also means that the real client component does
1546
not have focus -- has been deactivated... its xic should
1547
not have the focus, bug#4284651 showes reset XIC for htt
1548
may bring the focus back, so de-focus it again.
1549
*/
1550
setXICFocus(pX11IMData->ic_active, FALSE);
1551
if (pX11IMData->ic_active != pX11IMData->ic_passive) {
1552
char *tmpText = XmbResetIC(pX11IMData->ic_passive);
1553
setXICFocus(pX11IMData->ic_passive, FALSE);
1554
if (xText == (char *)NULL && tmpText)
1555
xText = tmpText;
1556
}
1557
1558
}
1559
if (xText != NULL) {
1560
jText = JNU_NewStringPlatform(env, (const char *)xText);
1561
XFree((void *)xText);
1562
}
1563
1564
AWT_UNLOCK();
1565
return jText;
1566
}
1567
1568
/*
1569
* Class: sun_awt_X11InputMethod
1570
* Method: setCompositionEnabledNative
1571
* Signature: (ZJ)V
1572
*
1573
* This method tries to set the XNPreeditState attribute associated with the current
1574
* XIC to the passed in 'enable' state.
1575
*
1576
* Return JNI_TRUE if XNPreeditState attribute is successfully changed to the
1577
* 'enable' state; Otherwise, if XSetICValues fails to set this attribute,
1578
* java.lang.UnsupportedOperationException will be thrown. JNI_FALSE is returned if this
1579
* method fails due to other reasons.
1580
*
1581
*/
1582
JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethod_setCompositionEnabledNative
1583
(JNIEnv *env, jobject this, jboolean enable)
1584
{
1585
X11InputMethodData *pX11IMData;
1586
char * ret = NULL;
1587
1588
AWT_LOCK();
1589
pX11IMData = getX11InputMethodData(env, this);
1590
1591
if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) {
1592
AWT_UNLOCK();
1593
return JNI_FALSE;
1594
}
1595
1596
ret = XSetICValues(pX11IMData->current_ic, XNPreeditState,
1597
(enable ? XIMPreeditEnable : XIMPreeditDisable), NULL);
1598
AWT_UNLOCK();
1599
1600
if ((ret != 0) && (strcmp(ret, XNPreeditState) == 0)) {
1601
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");
1602
}
1603
1604
return (jboolean)(ret == 0);
1605
}
1606
1607
/*
1608
* Class: sun_awt_X11InputMethod
1609
* Method: isCompositionEnabledNative
1610
* Signature: (J)Z
1611
*
1612
* This method tries to get the XNPreeditState attribute associated with the current XIC.
1613
*
1614
* Return JNI_TRUE if the XNPreeditState is successfully retrieved. Otherwise, if
1615
* XGetICValues fails to get this attribute, java.lang.UnsupportedOperationException
1616
* will be thrown. JNI_FALSE is returned if this method fails due to other reasons.
1617
*
1618
*/
1619
JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethod_isCompositionEnabledNative
1620
(JNIEnv *env, jobject this)
1621
{
1622
X11InputMethodData *pX11IMData = NULL;
1623
char * ret = NULL;
1624
XIMPreeditState state;
1625
1626
AWT_LOCK();
1627
pX11IMData = getX11InputMethodData(env, this);
1628
1629
if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) {
1630
AWT_UNLOCK();
1631
return JNI_FALSE;
1632
}
1633
1634
ret = XGetICValues(pX11IMData->current_ic, XNPreeditState, &state, NULL);
1635
AWT_UNLOCK();
1636
1637
if ((ret != 0) && (strcmp(ret, XNPreeditState) == 0)) {
1638
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");
1639
return JNI_FALSE;
1640
}
1641
1642
return (jboolean)(state == XIMPreeditEnable);
1643
}
1644
1645
JNIEXPORT void JNICALL Java_sun_awt_X11_XInputMethod_adjustStatusWindow
1646
(JNIEnv *env, jobject this, jlong window)
1647
{
1648
#if defined(__linux__) || defined(MACOSX)
1649
AWT_LOCK();
1650
adjustStatusWindow(window);
1651
AWT_UNLOCK();
1652
#endif
1653
}
1654
1655