Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c
41152 views
1
/*
2
* Copyright (c) 1997, 2020, 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 "awt.h"
31
#include "awt_p.h"
32
33
#include <sun_awt_X11InputMethodBase.h>
34
#include <sun_awt_X11InputMethod.h>
35
#include <sun_awt_X11_XInputMethod.h>
36
37
#include <langinfo.h>
38
#include <stdio.h>
39
#include <stdlib.h>
40
#include <sys/time.h>
41
#include <wchar.h>
42
#include <wctype.h>
43
#include <X11/Intrinsic.h>
44
#include <X11/keysym.h>
45
#include <X11/Xlib.h>
46
47
#define THROW_OUT_OF_MEMORY_ERROR() \
48
JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL)
49
50
struct X11InputMethodIDs {
51
jfieldID pData;
52
} x11InputMethodIDs;
53
54
static int PreeditStartCallback(XIC, XPointer, XPointer);
55
static void PreeditDoneCallback(XIC, XPointer, XPointer);
56
static void PreeditDrawCallback(XIC, XPointer,
57
XIMPreeditDrawCallbackStruct *);
58
static void PreeditCaretCallback(XIC, XPointer,
59
XIMPreeditCaretCallbackStruct *);
60
static void StatusStartCallback(XIC, XPointer, XPointer);
61
static void StatusDoneCallback(XIC, XPointer, XPointer);
62
static void StatusDrawCallback(XIC, XPointer,
63
XIMStatusDrawCallbackStruct *);
64
65
#define ROOT_WINDOW_STYLES (XIMPreeditNothing | XIMStatusNothing)
66
#define NO_STYLES (XIMPreeditNone | XIMStatusNone)
67
/* added style to allow for in-place composition, such as "dead" keys for accents */
68
#define IN_PLACE_STYLES (XIMPreeditNothing | XIMStatusNone)
69
70
#define PreeditStartIndex 0
71
#define PreeditDoneIndex 1
72
#define PreeditDrawIndex 2
73
#define PreeditCaretIndex 3
74
#define StatusStartIndex 4
75
#define StatusDoneIndex 5
76
#define StatusDrawIndex 6
77
#define NCALLBACKS 7
78
79
#define STATUS_BORDER 2 /* Status Border width */
80
#define CARET_OFFSET 1 /* Offset of caret position (pixel) */
81
#define BORDER_MARGIN 3 /* BORDER MARGIN width */
82
#define STATUS_MARGIN 7 /* Margin between the status window and its parent window */
83
#define PREEDIT_ATTR_MASK (XIMReverse|XIMUnderline)
84
/* Preedit attribute which host adapter can handle */
85
86
/*
87
* Callback function pointers: the order has to match the *Index
88
* values above.
89
*/
90
static XIMProc callback_funcs[NCALLBACKS] = {
91
(XIMProc)(void *)&PreeditStartCallback,
92
(XIMProc)PreeditDoneCallback,
93
(XIMProc)PreeditDrawCallback,
94
(XIMProc)PreeditCaretCallback,
95
(XIMProc)StatusStartCallback,
96
(XIMProc)StatusDoneCallback,
97
(XIMProc)StatusDrawCallback,
98
};
99
100
#define MAX_STATUS_LEN 100
101
typedef struct {
102
Window w; /*status window id */
103
Window root; /*the root window id */
104
Window parent; /*parent shell window */
105
Window grandParent; /*window has WM frame */
106
int x, y; /*parent's upperleft position */
107
int width, height; /*parent's width, height */
108
GC lightGC; /*gc for light border */
109
GC dimGC; /*gc for dim border */
110
GC bgGC; /*normal painting */
111
GC fgGC; /*normal painting */
112
int statusW, statusH; /*status window's w, h */
113
int rootW, rootH; /*root window's w, h */
114
int bWidth; /*border width */
115
wchar_t status[MAX_STATUS_LEN + 1]; /*status text */
116
XFontSet fontset; /*fontset for drawing */
117
int off_x, off_y;
118
Bool on; /*if the status window on*/
119
int fOff; /* font base line(in pixel) from top */
120
int fBot; /* font bottom line(in pixel) from top */
121
int peTextW; /* Composition text width in pixel */
122
wchar_t* peText; /* Composed string (wide char.) */
123
XIMFeedback* peAttr; /* Composed text attribute */
124
int peCaret; /* Caret position in number of character */
125
Bool status_ready; /* Not draw Status at XCreateIC */
126
} StatusWindow;
127
128
/*
129
* X11InputMethodData keeps per X11InputMethod instance information. A pointer
130
* to this data structure is kept in an X11InputMethod object (pData).
131
*/
132
typedef struct _X11InputMethodData {
133
XIC current_ic; /* current X Input Context */
134
XIC ic_active; /* X Input Context for active clients */
135
XIC ic_passive; /* X Input Context for passive clients */
136
XIMCallback *callbacks; /* callback parameters */
137
jobject x11inputmethod; /* global ref to X11InputMethod instance */
138
/* associated with the XIC */
139
StatusWindow *statusWindow; /* our own status window */
140
Bool passiveStatusWindow;/* Passive Client uses StatusWindow */
141
Bool isActiveClient; /* True:clinet is active */
142
Bool forceReset; /* True: call resetXIC before UnsetICFocus */
143
} X11InputMethodData;
144
145
/* reference to the current X11InputMethod instance, it is always
146
point to the global reference to the X11InputMethodObject since
147
it could be referenced by different threads. */
148
jobject currentX11InputMethodInstance = NULL;
149
150
Window currentFocusWindow = 0; /* current window that has focus for input
151
method. (the best place to put this
152
information should be
153
currentX11InputMethodInstance's pData) */
154
static XIM X11im = NULL;
155
Display * dpy = NULL;
156
157
#define GetJNIEnv() (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2)
158
159
static X11InputMethodData * getX11InputMethodData(JNIEnv *, jobject);
160
static void setX11InputMethodData(JNIEnv *, jobject, X11InputMethodData *);
161
static void destroyX11InputMethodData(JNIEnv *, X11InputMethodData *);
162
static void freeX11InputMethodData(JNIEnv *, X11InputMethodData *);
163
164
/* Prototype for this function is missing in AIX Xlib.h */
165
extern char *XSetIMValues(
166
#if NeedVarargsPrototypes
167
XIM /* im */, ...
168
#endif
169
);
170
171
static int st_wcslen(wchar_t *string);
172
static Bool isPreeditStateActive(XIC ic);
173
static void * buf_insert(void * src, void * insert, int size,
174
int src_len, int ins_len, int offset);
175
static void * handle_buffer(void * source, void * insert,
176
int size, int src_len, int ins_len,
177
int del_len, int offset);
178
static void preedit_draw_passive(X11InputMethodData *pX11IMData,
179
XIMPreeditDrawCallbackStruct *pre_draw);
180
static void resetPassivePreeditText(StatusWindow *statusWindow);
181
static void draw_caret(StatusWindow *statusWindow, GC gc, int pos);
182
static int get_next_attr(int len, unsigned long *attr);
183
static void draw_preedit(StatusWindow *statusWindow);
184
static void align_status(StatusWindow *statusWindow);
185
static void shrink_status(StatusWindow *statusWindow);
186
static XFontSet create_fontset(void);
187
static Bool is_text_available(XIMText * text);
188
static Bool isNativeIm();
189
static Window getGrandParent(Window parent);
190
static void moveStatusWindow(StatusWindow *statusWindow);
191
static void arrange_window_stack(StatusWindow* statusWindow);
192
static Window get_current_focus(XIC ic);
193
194
/*
195
* This function is stolen from /src/solaris/hpi/src/system_md.c
196
* It is used in setting the time in Java-level InputEvents
197
*/
198
jlong
199
awt_util_nowMillisUTC()
200
{
201
struct timeval t;
202
gettimeofday(&t, NULL);
203
return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000);
204
}
205
206
/*
207
* Converts the wchar_t string to a multi-byte string calling wcstombs(). A
208
* buffer is allocated by malloc() to store the multi-byte string. NULL is
209
* returned if the given wchar_t string pointer is NULL or buffer allocation is
210
* failed.
211
*/
212
static char *
213
wcstombsdmp(wchar_t *wcs, int len)
214
{
215
size_t n;
216
char *mbs;
217
218
if (wcs == NULL)
219
return NULL;
220
221
n = len*MB_CUR_MAX + 1;
222
223
mbs = (char *) malloc(n * sizeof(char));
224
if (mbs == NULL) {
225
THROW_OUT_OF_MEMORY_ERROR();
226
return NULL;
227
}
228
229
/* TODO: check return values... Handle invalid characters properly... */
230
if (wcstombs(mbs, wcs, n) == (size_t)-1) {
231
free(mbs);
232
return NULL;
233
}
234
235
return mbs;
236
}
237
238
static X11InputMethodData * getX11InputMethodData(JNIEnv * env, jobject imInstance) {
239
X11InputMethodData *pX11IMData =
240
(X11InputMethodData *)JNU_GetLongFieldAsPtr(env, imInstance, x11InputMethodIDs.pData);
241
242
/*
243
* In case the XIM server was killed somehow, reset X11InputMethodData.
244
*/
245
if (X11im == NULL && pX11IMData != NULL) {
246
JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
247
"flushText",
248
"()V");
249
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
250
/* IMPORTANT:
251
The order of the following calls is critical since "imInstance" may
252
point to the global reference itself, if "freeX11InputMethodData" is called
253
first, the global reference will be destroyed and "setX11InputMethodData"
254
will in fact fail silently. So pX11IMData will not be set to NULL.
255
This could make the original java object refers to a deleted pX11IMData
256
object.
257
*/
258
setX11InputMethodData(env, imInstance, NULL);
259
freeX11InputMethodData(env, pX11IMData);
260
pX11IMData = NULL;
261
}
262
263
return pX11IMData;
264
}
265
266
static void setX11InputMethodData(JNIEnv * env, jobject imInstance, X11InputMethodData *pX11IMData) {
267
JNU_SetLongFieldFromPtr(env, imInstance, x11InputMethodIDs.pData, pX11IMData);
268
}
269
270
/* this function should be called within AWT_LOCK() */
271
static void
272
destroyX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData)
273
{
274
/*
275
* Destroy XICs
276
*/
277
if (pX11IMData == NULL) {
278
return;
279
}
280
281
if (pX11IMData->ic_active != (XIC)0) {
282
XUnsetICFocus(pX11IMData->ic_active);
283
XDestroyIC(pX11IMData->ic_active);
284
if (pX11IMData->ic_active != pX11IMData->ic_passive) {
285
if (pX11IMData->ic_passive != (XIC)0) {
286
XUnsetICFocus(pX11IMData->ic_passive);
287
XDestroyIC(pX11IMData->ic_passive);
288
}
289
pX11IMData->ic_passive = (XIC)0;
290
pX11IMData->current_ic = (XIC)0;
291
}
292
}
293
294
freeX11InputMethodData(env, pX11IMData);
295
}
296
297
static void
298
freeX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData)
299
{
300
if (pX11IMData->statusWindow != NULL){
301
StatusWindow *sw = pX11IMData->statusWindow;
302
XFreeGC(awt_display, sw->lightGC);
303
XFreeGC(awt_display, sw->dimGC);
304
XFreeGC(awt_display, sw->bgGC);
305
XFreeGC(awt_display, sw->fgGC);
306
if (sw->fontset != NULL) {
307
XFreeFontSet(awt_display, sw->fontset);
308
}
309
XDestroyWindow(awt_display, sw->w);
310
if (pX11IMData->statusWindow->peText){
311
free((void *)pX11IMData->statusWindow->peText);
312
pX11IMData->statusWindow->peText = NULL;
313
}
314
if (pX11IMData->statusWindow->peAttr){
315
free((void *)pX11IMData->statusWindow->peAttr);
316
pX11IMData->statusWindow->peAttr = NULL;
317
}
318
free((void*)sw);
319
}
320
321
if (pX11IMData->callbacks)
322
free((void *)pX11IMData->callbacks);
323
324
if (env) {
325
(*env)->DeleteGlobalRef(env, pX11IMData->x11inputmethod);
326
}
327
328
free((void *)pX11IMData);
329
}
330
331
/*
332
* Sets or unsets the focus to the given XIC.
333
*/
334
static void
335
setXICFocus(XIC ic, unsigned short req)
336
{
337
if (ic == NULL) {
338
(void)fprintf(stderr, "Couldn't find X Input Context\n");
339
return;
340
}
341
if (req == 1)
342
XSetICFocus(ic);
343
else
344
XUnsetICFocus(ic);
345
}
346
347
/*
348
* Sets the focus window to the given XIC.
349
*/
350
static void
351
setXICWindowFocus(XIC ic, Window w)
352
{
353
if (ic == NULL) {
354
(void)fprintf(stderr, "Couldn't find X Input Context\n");
355
return;
356
}
357
(void) XSetICValues(ic, XNFocusWindow, w, NULL);
358
}
359
360
/*
361
* Invokes XmbLookupString() to get something from the XIM. It invokes
362
* X11InputMethod.dispatchCommittedText() if XmbLookupString() returns
363
* committed text. This function is called from handleKeyEvent in canvas.c and
364
* it's under the Motif event loop thread context.
365
*
366
* Buffer usage: There is a bug in XFree86-4.3.0 XmbLookupString implementation,
367
* where it never returns XBufferOverflow. We need to allocate the initial lookup buffer
368
* big enough, so that the possibility that user encounters this problem is relatively
369
* small. When this bug gets fixed, we can make the initial buffer size smaller.
370
* Note that XmbLookupString() sometimes produces a non-null-terminated string.
371
*
372
* Returns True when there is a keysym value to be handled.
373
*/
374
#define INITIAL_LOOKUP_BUF_SIZE 512
375
376
Boolean
377
awt_x11inputmethod_lookupString(XKeyPressedEvent *event, KeySym *keysymp)
378
{
379
JNIEnv *env = GetJNIEnv();
380
X11InputMethodData *pX11IMData = NULL;
381
int buf_len = INITIAL_LOOKUP_BUF_SIZE;
382
char mbbuf[INITIAL_LOOKUP_BUF_SIZE];
383
char *buf;
384
KeySym keysym = NoSymbol;
385
Status status;
386
int mblen;
387
jstring javastr;
388
XIC ic;
389
Boolean result = True;
390
static Boolean composing = False;
391
392
/*
393
printf("lookupString: entering...\n");
394
*/
395
396
pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance);
397
398
if (pX11IMData == NULL) {
399
return False;
400
}
401
402
if ((ic = pX11IMData->current_ic) == (XIC)0){
403
return False;
404
}
405
406
buf = mbbuf;
407
mblen = XmbLookupString(ic, event, buf,
408
buf_len - 1, &keysym, &status);
409
410
/*
411
* In case of overflow, a buffer is allocated and it retries
412
* XmbLookupString().
413
*/
414
if (status == XBufferOverflow) {
415
buf_len = mblen + 1;
416
buf = (char *)malloc(buf_len);
417
if (buf == NULL) {
418
THROW_OUT_OF_MEMORY_ERROR();
419
return result;
420
}
421
mblen = XmbLookupString(ic, event, buf, buf_len, &keysym, &status);
422
}
423
buf[mblen] = 0;
424
425
/* Get keysym without taking modifiers into account first to map
426
* to AWT keyCode table.
427
*/
428
switch (status) {
429
case XLookupBoth:
430
if (!composing) {
431
if (event->keycode != 0) {
432
*keysymp = keysym;
433
result = False;
434
break;
435
}
436
}
437
composing = False;
438
/*FALLTHRU*/
439
case XLookupChars:
440
/*
441
printf("lookupString: status=XLookupChars, type=%d, state=%x, keycode=%x, keysym=%x\n",
442
event->type, event->state, event->keycode, keysym);
443
*/
444
javastr = JNU_NewStringPlatform(env, (const char *)buf);
445
if (javastr != NULL) {
446
JNU_CallMethodByName(env, NULL,
447
currentX11InputMethodInstance,
448
"dispatchCommittedText",
449
"(Ljava/lang/String;J)V",
450
javastr,
451
event->time);
452
if ((*env)->ExceptionOccurred(env)) {
453
(*env)->ExceptionDescribe(env);
454
(*env)->ExceptionClear(env);
455
}
456
}
457
break;
458
459
case XLookupKeySym:
460
/*
461
printf("lookupString: status=XLookupKeySym, type=%d, state=%x, keycode=%x, keysym=%x\n",
462
event->type, event->state, event->keycode, keysym);
463
*/
464
if (keysym == XK_Multi_key)
465
composing = True;
466
if (! composing) {
467
*keysymp = keysym;
468
result = False;
469
}
470
break;
471
472
case XLookupNone:
473
/*
474
printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n",
475
event->type, event->state, event->keycode, keysym);
476
*/
477
break;
478
}
479
480
if (buf != mbbuf) {
481
free(buf);
482
}
483
return result;
484
}
485
486
static StatusWindow *createStatusWindow(Window parent) {
487
StatusWindow *statusWindow;
488
XSetWindowAttributes attrib;
489
unsigned long attribmask;
490
Window containerWindow;
491
Window status;
492
Window child;
493
XWindowAttributes xwa;
494
XWindowAttributes xxwa;
495
/* Variable for XCreateFontSet()*/
496
char **mclr;
497
int mccr = 0;
498
char *dsr;
499
unsigned long bg, fg, light, dim;
500
int x, y, off_x, off_y, xx, yy;
501
unsigned int w, h, bw, depth;
502
XGCValues values;
503
unsigned long valuemask = 0; /*ignore XGCvalue and use defaults*/
504
int screen = 0;
505
int i;
506
AwtGraphicsConfigDataPtr adata;
507
extern int awt_numScreens;
508
/*hardcode the size right now, should get the size base on font*/
509
int width=80, height=22;
510
Window rootWindow;
511
Window *ignoreWindowPtr;
512
unsigned int ignoreUnit;
513
Window grandParent;
514
Window target;
515
XFontSet fontset;
516
517
fontset = create_fontset();
518
if (NULL == fontset) {
519
return NULL;
520
}
521
522
XGetGeometry(dpy, parent, &rootWindow, &x, &y, &w, &h, &bw, &depth);
523
524
attrib.override_redirect = True;
525
attribmask = CWOverrideRedirect;
526
for (i = 0; i < awt_numScreens; i++) {
527
if (RootWindow(dpy, i) == rootWindow) {
528
screen = i;
529
break;
530
}
531
}
532
adata = getDefaultConfig(screen);
533
bg = adata->AwtColorMatch(255, 255, 255, adata);
534
fg = adata->AwtColorMatch(0, 0, 0, adata);
535
light = adata->AwtColorMatch(195, 195, 195, adata);
536
dim = adata->AwtColorMatch(128, 128, 128, adata);
537
538
grandParent = getGrandParent(parent);
539
target = (grandParent == 0) ? parent : grandParent;
540
XGetWindowAttributes(dpy, target, &xwa);
541
bw = 2; /*xwa.border_width does not have the correct value*/
542
543
/*compare the size difference between parent container
544
and shell widget, the diff should be the border frame
545
and title bar height (?)*/
546
547
XQueryTree( dpy,
548
target,
549
&rootWindow,
550
&containerWindow,
551
&ignoreWindowPtr,
552
&ignoreUnit);
553
XGetWindowAttributes(dpy, containerWindow, &xxwa);
554
555
XTranslateCoordinates(dpy,
556
target, xwa.root,
557
0, 0,
558
&x, &y, &child);
559
560
if (containerWindow == rootWindow) {
561
off_x = 0; off_y = STATUS_MARGIN;
562
} else {
563
XGetWindowAttributes(dpy, containerWindow, &xxwa);
564
off_x = (xxwa.width - xwa.width) / 2;
565
/* off_y = xxwa.height - xwa.height - off_x;*/ /*it's magic:-) */
566
{
567
int cx, cy;
568
XTranslateCoordinates(dpy,
569
containerWindow, xxwa.root,
570
0, 0,
571
&cx, &cy,
572
&child);
573
off_y = (xxwa.height + cy) - (xwa.height + y);
574
}
575
}
576
577
/*get the size of root window*/
578
XGetWindowAttributes(dpy, rootWindow, &xxwa);
579
580
XTranslateCoordinates(dpy,
581
target, xwa.root,
582
xwa.x, xwa.y,
583
&x, &y,
584
&child);
585
xx = x - off_x;
586
yy = y + xwa.height - off_y;
587
if (xx < 0 ){
588
xx = 0;
589
}
590
if (xx + width > xxwa.width) {
591
xx = xxwa.width - width;
592
}
593
if (yy + height > xxwa.height) {
594
yy = xxwa.height - height;
595
}
596
597
if ((DefaultVisual(dpy,screen))->class != adata->awt_visInfo.visual->class &&
598
adata->awt_visInfo.visual->class == TrueColor) {
599
attrib.colormap = XCreateColormap(dpy, xwa.root,
600
adata->awt_visInfo.visual, AllocNone );
601
attrib.border_pixel = BlackPixel(dpy, screen) ;
602
attribmask |= CWColormap | CWBorderPixel;
603
}
604
605
status = XCreateWindow(dpy,
606
xwa.root,
607
xx, yy,
608
width, height,
609
0,
610
xwa.depth,
611
InputOutput,
612
adata->awt_visInfo.visual,
613
attribmask, &attrib);
614
XSelectInput(dpy, status,
615
ExposureMask | StructureNotifyMask | EnterWindowMask |
616
LeaveWindowMask | VisibilityChangeMask);
617
if (grandParent != 0){
618
long mask;
619
XGetWindowAttributes(dpy, grandParent, &xwa);
620
mask = xwa.your_event_mask | StructureNotifyMask |
621
VisibilityChangeMask | PropertyChangeMask;
622
XSelectInput(dpy, grandParent,mask);
623
}
624
625
statusWindow = (StatusWindow*) calloc(1, sizeof(StatusWindow));
626
if (statusWindow == NULL){
627
THROW_OUT_OF_MEMORY_ERROR();
628
return NULL;
629
}
630
statusWindow->w = status;
631
statusWindow->fontset = fontset;
632
statusWindow->parent = parent;
633
statusWindow->grandParent = grandParent;
634
statusWindow->on = False;
635
statusWindow->x = x;
636
statusWindow->y = y;
637
statusWindow->width = xwa.width;
638
statusWindow->height = xwa.height;
639
statusWindow->off_x = off_x;
640
statusWindow->off_y = off_y;
641
statusWindow->bWidth = bw;
642
statusWindow->statusH = height;
643
statusWindow->statusW = width;
644
statusWindow->peTextW = 0;
645
statusWindow->rootH = xxwa.height;
646
statusWindow->rootW = xxwa.width;
647
statusWindow->lightGC = XCreateGC(dpy, status, valuemask, &values);
648
XSetForeground(dpy, statusWindow->lightGC, light);
649
statusWindow->dimGC = XCreateGC(dpy, status, valuemask, &values);
650
XSetForeground(dpy, statusWindow->dimGC, dim);
651
statusWindow->fgGC = XCreateGC(dpy, status, valuemask, &values);
652
XSetForeground(dpy, statusWindow->fgGC, fg);
653
XSetBackground(dpy, statusWindow->fgGC, bg);
654
statusWindow->bgGC = XCreateGC(dpy, status, valuemask, &values);
655
XSetForeground(dpy, statusWindow->bgGC, bg);
656
XSetBackground(dpy, statusWindow->bgGC, fg);
657
statusWindow->status_ready = False;
658
wcscpy(statusWindow->status, L"");
659
return statusWindow;
660
}
661
662
/* This method is to turn off or turn on the status window. */
663
static void onoffStatusWindow(X11InputMethodData* pX11IMData,
664
Window parent,
665
Bool ON){
666
XWindowAttributes xwa;
667
Window child;
668
int x, y;
669
StatusWindow *statusWindow = NULL;
670
671
if (NULL == pX11IMData ||
672
NULL == (statusWindow = pX11IMData->statusWindow)){
673
return;
674
}
675
676
if (ON == False) {
677
XUnmapWindow(dpy, statusWindow->w);
678
return;
679
}
680
if (NULL == currentX11InputMethodInstance){
681
return;
682
}
683
{
684
JNIEnv *env = GetJNIEnv();
685
parent = JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
686
"getCurrentParentWindow",
687
"()J").j;
688
if ((*env)->ExceptionOccurred(env)) {
689
(*env)->ExceptionDescribe(env);
690
(*env)->ExceptionClear(env);
691
}
692
}
693
if (statusWindow->parent != parent) {
694
statusWindow->parent = parent;
695
}
696
if (st_wcslen(statusWindow->status) > 0 ||
697
(statusWindow->peText != NULL && st_wcslen(statusWindow->peText) > 0 )) {
698
moveStatusWindow(statusWindow);
699
XMapRaised(dpy, statusWindow->w);
700
}
701
}
702
703
void paintStatusWindow(StatusWindow *statusWindow){
704
Window win = statusWindow->w;
705
GC lightgc = statusWindow->lightGC;
706
GC dimgc = statusWindow->dimGC;
707
GC bggc = statusWindow->bgGC;
708
GC fggc = statusWindow->fgGC;
709
710
int width = statusWindow->statusW;
711
int height = statusWindow->statusH;
712
int bwidth = statusWindow->bWidth;
713
int len;
714
XRectangle logical, ink;
715
716
if (NULL == statusWindow) return;
717
if ((len = st_wcslen(statusWindow->status)) == 0) {
718
return;
719
}
720
XwcTextExtents(statusWindow->fontset, statusWindow->status,
721
len, &ink, &logical);
722
width = logical.width;
723
height = logical.height;
724
725
XFillRectangle(dpy, win, bggc, 0, 0, width+2, height+2);
726
727
XDrawLine(dpy, win, fggc, 0, 0, width+2, 0);
728
XDrawLine(dpy, win, fggc, 0, height+2, width+2, height+2);
729
XDrawLine(dpy, win, fggc, 0, 0, 0, height+2);
730
XDrawLine(dpy, win, fggc, width+2, 0, width+2, height+2);
731
732
if (statusWindow->fontset) {
733
XwcDrawString(dpy, win, statusWindow->fontset, fggc,
734
-logical.x + 1, -logical.y + 1,
735
statusWindow->status,
736
st_wcslen(statusWindow->status));
737
} else {
738
/*too bad we failed to create a fontset for this locale*/
739
XDrawString(dpy, win, fggc, bwidth + 2, height - bwidth - 4,
740
"[InputMethod ON]", strlen("[InputMethod ON]"));
741
}
742
}
743
744
Bool statusWindowEventHandler(XEvent event) {
745
JNIEnv *env = GetJNIEnv();
746
X11InputMethodData *pX11IMData = NULL;
747
StatusWindow *statusWindow;
748
749
if (NULL == currentX11InputMethodInstance ||
750
NULL == (pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance)) ||
751
NULL == (statusWindow = pX11IMData->statusWindow))
752
{
753
return False;
754
}
755
756
if (statusWindow->w == event.xany.window) {
757
switch (event.type) {
758
case Expose:
759
paintStatusWindow(statusWindow);
760
if (statusWindow->peText)
761
draw_preedit(statusWindow);
762
arrange_window_stack(statusWindow);
763
break;
764
case ConfigureNotify:
765
case VisibilityNotify:
766
arrange_window_stack(statusWindow);
767
break;
768
/*
769
case UnmapNotify:
770
case VisibilityNotify:
771
break;
772
*/
773
default:
774
break;
775
}
776
return True;
777
} else if ((statusWindow->parent == event.xany.window) ||
778
(statusWindow->grandParent && statusWindow->grandParent == event.xany.window)) {
779
switch (event.type) {
780
case MapNotify:
781
if (statusWindow->on) {
782
onoffStatusWindow(pX11IMData, statusWindow->parent, True);
783
}
784
break;
785
case UnmapNotify:
786
onoffStatusWindow(pX11IMData, 0, False);
787
break;
788
case VisibilityNotify:
789
if (statusWindow->on) {
790
arrange_window_stack(statusWindow);
791
}
792
break;
793
case ConfigureNotify:
794
if (statusWindow->grandParent && statusWindow->on) {
795
moveStatusWindow(statusWindow);
796
}
797
case PropertyNotify:
798
if (statusWindow->on) {
799
arrange_window_stack(statusWindow);
800
}
801
break;
802
default:
803
break;
804
}
805
}
806
return False;
807
}
808
809
static void adjustStatusWindow(Window shell) {
810
JNIEnv *env = GetJNIEnv();
811
X11InputMethodData *pX11IMData = NULL;
812
StatusWindow *statusWindow;
813
814
if (NULL == currentX11InputMethodInstance
815
|| NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))
816
|| NULL == (statusWindow = pX11IMData->statusWindow)
817
|| !statusWindow->on)
818
{
819
return;
820
}
821
822
moveStatusWindow(statusWindow);
823
}
824
825
/*
826
* Creates two XICs, one for active clients and the other for passive
827
* clients. All information on those XICs are stored in the
828
* X11InputMethodData given by the pX11IMData parameter.
829
*
830
* For active clients: Try to use preedit callback to support
831
* on-the-spot. If tc is not null, the XIC to be created will
832
* share the Status Area with Motif widgets (TextComponents). If the
833
* preferable styles can't be used, fallback to root-window styles. If
834
* root-window styles failed, fallback to None styles.
835
*
836
* For passive clients: Try to use root-window styles. If failed,
837
* fallback to None styles.
838
*/
839
static Bool
840
createXIC(JNIEnv * env, X11InputMethodData *pX11IMData, Window w)
841
{
842
XVaNestedList preedit = NULL;
843
XVaNestedList status = NULL;
844
XIMStyle on_the_spot_styles = XIMPreeditCallbacks,
845
in_place_styles = 0,
846
active_styles = 0,
847
passive_styles = 0,
848
no_styles = 0;
849
XIMCallback *callbacks;
850
unsigned short i;
851
XIMStyles *im_styles;
852
char *ret = NULL;
853
Bool passiveStatusWindow = False;
854
pX11IMData->statusWindow = NULL;
855
856
if (X11im == NULL) {
857
return False;
858
}
859
if (!w) {
860
return False;
861
}
862
863
if (getenv("IBMJAVA_PASSIVE") == NULL) {
864
passiveStatusWindow = False;
865
} else {
866
passiveStatusWindow = True;
867
}
868
869
if (isNativeIm()) { passiveStatusWindow = True; }
870
871
ret = XGetIMValues(X11im, XNQueryInputStyle, &im_styles, NULL);
872
873
if (ret != NULL) {
874
jio_fprintf(stderr,"XGetIMValues: %s\n",ret);
875
return FALSE ;
876
}
877
878
on_the_spot_styles |= XIMStatusNothing;
879
880
/*kinput does not support XIMPreeditCallbacks and XIMStatusArea
881
at the same time, so use StatusCallback to draw the status
882
ourself
883
*/
884
for (i = 0; i < im_styles->count_styles; i++) {
885
if (im_styles->supported_styles[i] == (XIMPreeditCallbacks | XIMStatusCallbacks)) {
886
on_the_spot_styles = (XIMPreeditCallbacks | XIMStatusCallbacks);
887
break;
888
}
889
}
890
891
for (i = 0; i < im_styles->count_styles; i++) {
892
if (im_styles->supported_styles[i] == on_the_spot_styles)
893
active_styles = im_styles->supported_styles[i];
894
if (im_styles->supported_styles[i] == ROOT_WINDOW_STYLES)
895
passive_styles = im_styles->supported_styles[i];
896
if (im_styles->supported_styles[i] == IN_PLACE_STYLES) {
897
in_place_styles = im_styles->supported_styles[i];
898
}
899
if (im_styles->supported_styles[i] == NO_STYLES) {
900
no_styles = im_styles->supported_styles[i];
901
}
902
}
903
904
XFree(im_styles);
905
906
if (active_styles != on_the_spot_styles) {
907
if (passive_styles == ROOT_WINDOW_STYLES)
908
active_styles = passive_styles;
909
else {
910
if (in_place_styles == IN_PLACE_STYLES){
911
active_styles = passive_styles = IN_PLACE_STYLES;
912
} else {
913
if (no_styles == NO_STYLES)
914
active_styles = passive_styles = NO_STYLES;
915
else
916
active_styles = passive_styles = 0;
917
}
918
}
919
} else {
920
if (!passiveStatusWindow) {
921
if (passive_styles != ROOT_WINDOW_STYLES) {
922
if (no_styles == NO_STYLES)
923
active_styles = passive_styles = NO_STYLES;
924
else
925
active_styles = passive_styles = 0;
926
}
927
} else
928
passive_styles = active_styles;
929
}
930
931
if (active_styles == on_the_spot_styles) {
932
callbacks = (XIMCallback *)malloc(sizeof(XIMCallback) * NCALLBACKS);
933
if (callbacks == (XIMCallback *)NULL)
934
return False;
935
pX11IMData->callbacks = callbacks;
936
937
for (i = 0; i < NCALLBACKS; i++, callbacks++) {
938
callbacks->client_data = (XPointer) pX11IMData->x11inputmethod;
939
callbacks->callback = callback_funcs[i];
940
}
941
942
callbacks = pX11IMData->callbacks;
943
preedit = (XVaNestedList)XVaCreateNestedList(0,
944
XNPreeditStartCallback, &callbacks[PreeditStartIndex],
945
XNPreeditDoneCallback, &callbacks[PreeditDoneIndex],
946
XNPreeditDrawCallback, &callbacks[PreeditDrawIndex],
947
XNPreeditCaretCallback, &callbacks[PreeditCaretIndex],
948
NULL);
949
if (preedit == (XVaNestedList)NULL)
950
goto err;
951
/*always try XIMStatusCallbacks for active client...*/
952
{
953
if (on_the_spot_styles & XIMStatusCallbacks) {
954
status = (XVaNestedList)XVaCreateNestedList(0,
955
XNStatusStartCallback, &callbacks[StatusStartIndex],
956
XNStatusDoneCallback, &callbacks[StatusDoneIndex],
957
XNStatusDrawCallback, &callbacks[StatusDrawIndex],
958
NULL);
959
960
if (status == NULL)
961
goto err;
962
}
963
pX11IMData->statusWindow = createStatusWindow(w);
964
pX11IMData->ic_active = XCreateIC(X11im,
965
XNClientWindow, w,
966
XNFocusWindow, w,
967
XNInputStyle, active_styles,
968
XNPreeditAttributes, preedit,
969
XNStatusAttributes, status,
970
NULL);
971
if (NULL != pX11IMData->statusWindow) {
972
pX11IMData->statusWindow->status_ready = True;
973
}
974
XFree((void *)status);
975
XFree((void *)preedit);
976
}
977
if (passiveStatusWindow) {
978
pX11IMData->ic_passive = pX11IMData->ic_active;
979
} else {
980
pX11IMData->ic_passive = XCreateIC(X11im,
981
XNClientWindow, w,
982
XNFocusWindow, w,
983
XNInputStyle, passive_styles,
984
NULL);
985
}
986
} else {
987
pX11IMData->ic_active = XCreateIC(X11im,
988
XNClientWindow, w,
989
XNFocusWindow, w,
990
XNInputStyle, active_styles,
991
NULL);
992
pX11IMData->ic_passive = pX11IMData->ic_active;
993
}
994
995
// The code set the IC mode that the preedit state is not initialied
996
// at XmbResetIC. This attribute can be set at XCreateIC. I separately
997
// set the attribute to avoid the failure of XCreateIC at some platform
998
// which does not support the attribute.
999
if (pX11IMData->ic_active != 0)
1000
XSetICValues(pX11IMData->ic_active,
1001
XNResetState, XIMPreserveState, NULL);
1002
if (pX11IMData->ic_passive != 0 &&
1003
pX11IMData->ic_active != pX11IMData->ic_passive)
1004
XSetICValues(pX11IMData->ic_passive,
1005
XNResetState, XIMInitialState, NULL);
1006
1007
pX11IMData->passiveStatusWindow = passiveStatusWindow;
1008
1009
if (pX11IMData->ic_active == (XIC)0
1010
|| pX11IMData->ic_passive == (XIC)0) {
1011
return False;
1012
}
1013
1014
/* Unset focus to avoid unexpected IM on */
1015
setXICFocus(pX11IMData->ic_active, False);
1016
if (pX11IMData->ic_active != pX11IMData->ic_passive)
1017
setXICFocus(pX11IMData->ic_passive, False);
1018
1019
return True;
1020
1021
err:
1022
if (preedit)
1023
XFree((void *)preedit);
1024
THROW_OUT_OF_MEMORY_ERROR();
1025
return False;
1026
}
1027
1028
static int
1029
PreeditStartCallback(XIC ic, XPointer client_data, XPointer call_data)
1030
{
1031
JNIEnv *env = GetJNIEnv();
1032
X11InputMethodData *pX11IMData;
1033
1034
pX11IMData = getX11InputMethodData(env, (jobject)client_data);
1035
if (pX11IMData == NULL || pX11IMData->statusWindow == NULL) {
1036
return 0;
1037
}
1038
resetPassivePreeditText(pX11IMData->statusWindow);
1039
1040
return -1; /* unlimited length for preedit text */
1041
}
1042
1043
static void
1044
PreeditDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
1045
{
1046
JNIEnv *env = GetJNIEnv();
1047
X11InputMethodData *pX11IMData;
1048
1049
pX11IMData = getX11InputMethodData(env, (jobject)client_data);
1050
if (pX11IMData == NULL) {
1051
return;
1052
}
1053
1054
if (!pX11IMData->isActiveClient) {
1055
resetPassivePreeditText(pX11IMData->statusWindow);
1056
shrink_status(pX11IMData->statusWindow);
1057
}
1058
else{
1059
JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
1060
"clearComposedText",
1061
"(J)V",
1062
awt_util_nowMillisUTC());
1063
if ((*env)->ExceptionOccurred(env)) {
1064
(*env)->ExceptionDescribe(env);
1065
(*env)->ExceptionClear(env);
1066
}
1067
}
1068
}
1069
1070
/*
1071
* Translate the preedit draw callback items to Java values and invoke
1072
* X11InputMethod.dispatchComposedText().
1073
*
1074
* client_data: X11InputMethod object
1075
*/
1076
static void
1077
PreeditDrawCallback(XIC ic, XPointer client_data,
1078
XIMPreeditDrawCallbackStruct *pre_draw)
1079
{
1080
JNIEnv *env = GetJNIEnv();
1081
X11InputMethodData *pX11IMData = NULL;
1082
jmethodID x11imMethodID;
1083
1084
XIMText *text;
1085
jstring javastr = NULL;
1086
jintArray style = NULL;
1087
1088
/* printf("Native: PreeditDrawCallback() \n"); */
1089
if (pre_draw == NULL) {
1090
return;
1091
}
1092
AWT_LOCK();
1093
if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) {
1094
goto finally;
1095
}
1096
1097
if (!pX11IMData->isActiveClient){
1098
if (ic == pX11IMData->ic_passive) {
1099
preedit_draw_passive(pX11IMData, pre_draw);
1100
}
1101
goto finally;
1102
}
1103
1104
if ((text = pre_draw->text) != NULL) {
1105
if (is_text_available(text)) {
1106
if (text->string.multi_byte != NULL) {
1107
if (pre_draw->text->encoding_is_wchar == False) {
1108
javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte);
1109
if (javastr == NULL) {
1110
goto finally;
1111
}
1112
} else {
1113
char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
1114
if (mbstr == NULL) {
1115
goto finally;
1116
}
1117
javastr = JNU_NewStringPlatform(env, (const char *)mbstr);
1118
free(mbstr);
1119
if (javastr == NULL) {
1120
goto finally;
1121
}
1122
}
1123
}
1124
}
1125
if (text->feedback != NULL) {
1126
int cnt;
1127
jint *tmpstyle;
1128
1129
style = (*env)->NewIntArray(env, text->length);
1130
if (JNU_IsNull(env, style)) {
1131
(*env)->ExceptionClear(env);
1132
THROW_OUT_OF_MEMORY_ERROR();
1133
goto finally;
1134
}
1135
1136
if (sizeof(XIMFeedback) == sizeof(jint)) {
1137
/*
1138
* Optimization to avoid copying the array
1139
*/
1140
(*env)->SetIntArrayRegion(env, style, 0,
1141
text->length, (jint *)text->feedback);
1142
} else {
1143
tmpstyle = (jint *)malloc(sizeof(jint)*(text->length));
1144
if (tmpstyle == (jint *) NULL) {
1145
THROW_OUT_OF_MEMORY_ERROR();
1146
goto finally;
1147
}
1148
for (cnt = 0; cnt < (int)text->length; cnt++)
1149
tmpstyle[cnt] = text->feedback[cnt];
1150
(*env)->SetIntArrayRegion(env, style, 0,
1151
text->length, (jint *)tmpstyle);
1152
free(tmpstyle);
1153
}
1154
}
1155
}
1156
JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
1157
"dispatchComposedText",
1158
"(Ljava/lang/String;[IIIIJ)V",
1159
javastr,
1160
style,
1161
(jint)pre_draw->chg_first,
1162
(jint)pre_draw->chg_length,
1163
(jint)pre_draw->caret,
1164
awt_util_nowMillisUTC());
1165
1166
if ((*env)->ExceptionOccurred(env)) {
1167
(*env)->ExceptionDescribe(env);
1168
(*env)->ExceptionClear(env);
1169
}
1170
1171
finally:
1172
AWT_UNLOCK();
1173
return;
1174
}
1175
1176
static void
1177
PreeditCaretCallback(XIC ic, XPointer client_data,
1178
XIMPreeditCaretCallbackStruct *pre_caret)
1179
{
1180
XIMPreeditDrawCallbackStruct pre_draw;
1181
1182
if (pre_caret != NULL && pre_caret->direction == XIMAbsolutePosition) {
1183
pre_draw.caret = pre_caret->position;
1184
pre_draw.chg_first = 0;
1185
pre_draw.chg_length = 0;
1186
pre_draw.text = NULL;
1187
PreeditDrawCallback(ic, client_data, &pre_draw);
1188
}
1189
}
1190
1191
static void
1192
StatusStartCallback(XIC ic, XPointer client_data, XPointer call_data)
1193
{
1194
/*ARGSUSED*/
1195
/*printf("StatusStartCallback:\n"); */
1196
}
1197
1198
static void
1199
StatusDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
1200
{
1201
/*ARGSUSED*/
1202
/*printf("StatusDoneCallback:\n"); */
1203
}
1204
1205
static void StatusDrawCallback
1206
(XIC ic, XPointer client_data, XIMStatusDrawCallbackStruct *status_draw)
1207
{
1208
/*ARGSUSED*/
1209
/*printf("StatusDrawCallback:\n"); */
1210
JNIEnv *env = GetJNIEnv();
1211
X11InputMethodData *pX11IMData = NULL;
1212
StatusWindow *statusWindow;
1213
int value_make = CWX|CWWidth|CWHeight;
1214
XRectangle logical, ink;
1215
XWindowChanges xwc;
1216
int len;
1217
1218
AWT_LOCK();
1219
1220
if (NULL == (pX11IMData = getX11InputMethodData(env, (jobject)client_data))
1221
|| NULL == (statusWindow = pX11IMData->statusWindow)){
1222
goto finally;
1223
}
1224
1225
if (status_draw->type == XIMTextType) {
1226
XIMText *text = (status_draw->data).text;
1227
if (text != NULL) {
1228
if (text->string.multi_byte != NULL) {
1229
if(!strcmp(text->string.multi_byte," ")){
1230
wcscpy(statusWindow->status, L"");
1231
onoffStatusWindow(pX11IMData, 0, False);
1232
goto finally;
1233
}
1234
mbstowcs(statusWindow->status,
1235
(const char *)text->string.multi_byte,
1236
(size_t)MAX_STATUS_LEN);
1237
} else {
1238
if (0 == st_wcslen(text->string.wide_char)){
1239
wcscpy(statusWindow->status, L"");
1240
onoffStatusWindow(pX11IMData, 0, False);
1241
goto finally;
1242
}
1243
wcsncpy(statusWindow->status,
1244
text->string.wide_char,
1245
MAX_STATUS_LEN);
1246
}
1247
XwcTextExtents(statusWindow->fontset, statusWindow->status,
1248
st_wcslen(statusWindow->status), &ink, &logical);
1249
statusWindow->statusW = logical.width + BORDER_MARGIN;
1250
statusWindow->statusH = logical.height + BORDER_MARGIN;
1251
xwc.x = statusWindow->x - statusWindow->off_x;
1252
if (xwc.x < 0 ) xwc.x = 0;
1253
xwc.width = statusWindow->statusW;
1254
xwc.height = statusWindow->statusH;
1255
if (xwc.x + xwc.width > statusWindow->rootW){
1256
xwc.x = statusWindow->rootW - xwc.width;
1257
}
1258
XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
1259
if (statusWindow->status_ready && statusWindow->on == True){
1260
onoffStatusWindow(pX11IMData, statusWindow->parent, True);
1261
}
1262
paintStatusWindow(statusWindow);
1263
if (statusWindow->peText)
1264
draw_preedit(statusWindow);
1265
}
1266
else {
1267
wcscpy(statusWindow->status, L"");
1268
/*just turnoff the status window
1269
paintStatusWindow(statusWindow);
1270
*/
1271
onoffStatusWindow(pX11IMData, 0, False);
1272
}
1273
}
1274
1275
finally:
1276
AWT_UNLOCK();
1277
}
1278
1279
/* return the string length without trailing spaces */
1280
/* work around code for Japanese AIXIM is implemented. */
1281
static int st_wcslen(wchar_t *string)
1282
{
1283
int len = (int32_t)wcslen(string);
1284
if (len == 0)
1285
return 0;
1286
for (len--;len >= 0; len--) {
1287
if (!iswspace((wint_t) string[len])) break;
1288
}
1289
return len+1;
1290
}
1291
1292
/*
1293
* Checks whether given XIMText contains a string data.
1294
*/
1295
static Bool is_text_available(XIMText * text)
1296
{
1297
if (text == NULL || text->length==0)
1298
return False;
1299
if (text->encoding_is_wchar) {
1300
if(text->string.wide_char[0] == L'\0')
1301
return False;
1302
} else {
1303
if (text->string.multi_byte[0] == '\0')
1304
return False;
1305
}
1306
return True;
1307
}
1308
1309
/*
1310
* check if preedit status is active
1311
*/
1312
static Bool isPreeditStateActive(XIC ic)
1313
{
1314
XIMPreeditState state = XIMPreeditUnKnown;
1315
XVaNestedList pr_atrb;
1316
char* nosupportAttr;
1317
1318
if (ic == NULL) return False;
1319
1320
pr_atrb = XVaCreateNestedList(0,XNPreeditState,&state,NULL);
1321
nosupportAttr=XGetICValues(ic,XNPreeditAttributes,pr_atrb,NULL);
1322
XFree(pr_atrb);
1323
if (nosupportAttr==NULL && state & XIMPreeditDisable)
1324
return False;
1325
else
1326
return True;
1327
}
1328
1329
static void * buf_insert(void * src, void * insert, int size,
1330
int src_len, int ins_len, int offset)
1331
{
1332
char *temp;
1333
1334
temp = realloc(src, size*(src_len+ins_len+1));
1335
if (temp == NULL) {
1336
THROW_OUT_OF_MEMORY_ERROR();
1337
return src;
1338
}
1339
if (offset != src_len) {
1340
memmove(&temp[size*(offset+ins_len)],
1341
&((char *)temp)[size*offset],
1342
size*(src_len-offset));
1343
}
1344
memcpy(&temp[size*offset], insert, size*ins_len);
1345
1346
return (void *)temp;
1347
}
1348
1349
static void * handle_buffer(void * source, void * insert,
1350
int size,int src_len, int ins_len,
1351
int del_len, int offset)
1352
{
1353
void * temp = source;
1354
1355
if (del_len > 0) {
1356
if (del_len == ins_len) {
1357
memcpy(&((char *)source)[size*offset], insert, size*ins_len);
1358
return source;
1359
}
1360
else if (src_len > offset+del_len) {
1361
memmove(&((char *)source)[size*offset],
1362
&((char *)source)[size*(offset+del_len)],
1363
size*(src_len-offset-del_len));
1364
}
1365
}
1366
if (ins_len > 0) {
1367
temp = buf_insert(source, insert, size, src_len,
1368
ins_len, offset);
1369
}
1370
return temp;
1371
}
1372
/*
1373
* Display the given preedit text to the root window which is ownd by
1374
* myself. All of the character is converted to wide char.
1375
* this function is used for the passive client.
1376
*/
1377
static void preedit_draw_passive(X11InputMethodData *pX11IMData,
1378
XIMPreeditDrawCallbackStruct *pre_draw)
1379
{
1380
XIMText *text;
1381
wchar_t *tempbuf = NULL;
1382
StatusWindow *statusWindow;
1383
wchar_t *cur_text;
1384
unsigned long *cur_attr;
1385
int cur_len = 0;
1386
int chg_len = pre_draw->chg_length;
1387
int chg_1st = pre_draw->chg_first;
1388
1389
if (NULL == (statusWindow = pX11IMData->statusWindow))
1390
return;
1391
cur_text = statusWindow->peText;
1392
cur_attr = statusWindow->peAttr;
1393
if (cur_text == NULL && pre_draw->text == NULL)
1394
return;
1395
1396
if (cur_text != NULL)
1397
cur_len = (int32_t)wcslen(cur_text);
1398
text = pre_draw->text;
1399
if (text == NULL) {
1400
/* delete only */
1401
if (cur_len > chg_1st+chg_len) {
1402
memmove(&cur_text[chg_1st],
1403
&cur_text[chg_1st+chg_len],
1404
sizeof(wchar_t)*(cur_len-chg_1st-chg_len));
1405
memmove(&cur_attr[chg_1st],
1406
&cur_attr[chg_1st+chg_len],
1407
sizeof(long)*(cur_len-chg_1st-chg_len));
1408
}
1409
if ((pre_draw->chg_length <= cur_len ) && (pre_draw->chg_length >0))
1410
cur_text[cur_len-pre_draw->chg_length] =L'\0';
1411
} else {
1412
/* insert or replace */
1413
int ins_len = 0;
1414
void * ins_text = NULL;
1415
1416
/* if invalid offset is specified, do nothing. */
1417
/* this fix is for aixim for eucTW */
1418
if (cur_len < chg_1st)
1419
return;
1420
if(is_text_available(text)) {
1421
/* insert or replace the text */
1422
if (text->encoding_is_wchar == False) {
1423
/* convert the text to wide chars.
1424
allocate enough size buffer
1425
*/
1426
tempbuf = (wchar_t *)malloc(sizeof(wchar_t)*(text->length+1));
1427
if (tempbuf == NULL) {
1428
THROW_OUT_OF_MEMORY_ERROR();
1429
return;
1430
}
1431
ins_len = (int32_t)mbstowcs(tempbuf, text->string.multi_byte,
1432
text->length);
1433
if (ins_len == -1) {
1434
free(tempbuf);
1435
return;
1436
}
1437
ins_text = (void *)tempbuf;
1438
}
1439
else {
1440
ins_len = text->length;
1441
ins_text = text->string.wide_char;
1442
}
1443
/* finish prepare the data to be inserted */
1444
1445
statusWindow->peText =
1446
handle_buffer(cur_text, ins_text, sizeof(wchar_t),
1447
cur_len, ins_len, chg_len, chg_1st);
1448
statusWindow->peAttr =
1449
handle_buffer(cur_attr, text->feedback, sizeof(long),
1450
cur_len, ins_len, chg_len, chg_1st);
1451
statusWindow->peText[cur_len-chg_len+ins_len] =L'\0';
1452
1453
if (tempbuf != NULL)
1454
free(tempbuf);
1455
} /* endof insert or replace text */
1456
else {
1457
/* change attribute only */
1458
memcpy(&cur_attr[chg_1st], text->feedback,
1459
sizeof(long)*text->length);
1460
}
1461
}
1462
statusWindow->peCaret= pre_draw->caret;
1463
draw_preedit(statusWindow);
1464
if (statusWindow->on && wcslen(statusWindow->peText) > 0)
1465
onoffStatusWindow(pX11IMData, statusWindow->parent, True);
1466
else if (wcslen(statusWindow->status) == 0)
1467
onoffStatusWindow(pX11IMData, 0, False);
1468
}
1469
1470
/*
1471
* reset predit test of passive mode
1472
*/
1473
static void
1474
resetPassivePreeditText(StatusWindow *statusWindow)
1475
{
1476
if (NULL == statusWindow) return;
1477
if(statusWindow->peText != NULL) {
1478
free(statusWindow->peText);
1479
statusWindow->peText = NULL;
1480
}
1481
if(statusWindow->peAttr != NULL) {
1482
free(statusWindow->peAttr);
1483
statusWindow->peAttr = NULL;
1484
}
1485
statusWindow->peCaret= 0;
1486
}
1487
1488
static void draw_caret(StatusWindow *statusWindow, GC gc, int pos)
1489
{
1490
if (NULL == statusWindow) return;
1491
XSetFunction(dpy, gc, GXinvert);
1492
XDrawLine(dpy, statusWindow->w,
1493
gc, pos, STATUS_BORDER/2,
1494
pos, STATUS_BORDER/2+statusWindow->fOff);
1495
XSetFunction(dpy, gc, GXcopy);
1496
}
1497
1498
static int get_next_attr(int len, unsigned long *attr)
1499
{
1500
int count;
1501
1502
for (count = 1; count < len; count++) {
1503
if ((attr[count-1] & PREEDIT_ATTR_MASK)
1504
!= (attr[count] & PREEDIT_ATTR_MASK))
1505
break;
1506
}
1507
return count;
1508
}
1509
1510
static void draw_preedit(StatusWindow *statusWindow)
1511
{
1512
unsigned long *attr;
1513
int x_pos,x_caret;
1514
unsigned int len;
1515
int len_disp, pos;
1516
wchar_t *str;
1517
GC gc;
1518
XRectangle ink, rect, rect_c;
1519
Bool caret_done = False;
1520
1521
if (NULL == statusWindow) return;
1522
align_status(statusWindow);
1523
XFillRectangle(dpy, statusWindow->w,
1524
statusWindow->bgGC,
1525
statusWindow->statusW,0,
1526
statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN,
1527
statusWindow->fBot+2);
1528
1529
1530
XDrawLine(dpy, statusWindow->w, statusWindow->fgGC,
1531
statusWindow->statusW, 0,
1532
statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN, 0);
1533
XDrawLine(dpy, statusWindow->w, statusWindow->fgGC,
1534
statusWindow->statusW, statusWindow->fBot+2,
1535
statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN,
1536
statusWindow->fBot+2);
1537
XDrawLine(dpy, statusWindow->w, statusWindow->fgGC,
1538
statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN, 0,
1539
statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN,
1540
statusWindow->fBot+2);
1541
if (0 == statusWindow->statusW)
1542
XDrawLine(dpy, statusWindow->w, statusWindow->fgGC,
1543
0, 0, 0, statusWindow->fBot+2);
1544
1545
str = statusWindow->peText;
1546
1547
if (str != NULL && (len = (int32_t)wcslen(str)) != 0) {
1548
pos = 0;
1549
attr = statusWindow->peAttr;
1550
x_pos = x_caret = statusWindow->statusW + STATUS_BORDER;
1551
while((int)len-1 >= pos) {
1552
len_disp = get_next_attr(len - pos, &attr[pos]);
1553
if (attr[pos] & XIMReverse) {
1554
gc = statusWindow->bgGC;
1555
}
1556
else {
1557
gc = statusWindow->fgGC;
1558
}
1559
XwcTextExtents(statusWindow->fontset,
1560
&str[pos],
1561
len_disp, &ink, &rect);
1562
XwcDrawImageString(dpy, statusWindow->w,
1563
statusWindow->fontset, gc,
1564
x_pos, statusWindow->fOff+1, &str[pos], len_disp);
1565
if (attr[pos] & XIMUnderline) {
1566
XDrawLine(dpy, statusWindow->w,
1567
gc, x_pos, statusWindow->fBot,
1568
x_pos+rect.width, statusWindow->fBot);
1569
}
1570
if (!caret_done) {
1571
if( statusWindow->peCaret >= pos &&
1572
statusWindow->peCaret <= pos+len_disp) {
1573
if (statusWindow->peCaret == 0)
1574
x_caret = x_pos;
1575
else if (statusWindow->peCaret == pos+len_disp)
1576
x_caret = x_pos+rect.width;
1577
else {
1578
XwcTextExtents(statusWindow->fontset,
1579
&str[pos],
1580
statusWindow->peCaret-pos,
1581
&ink, &rect_c);
1582
x_caret = x_pos+ rect_c.width;
1583
}
1584
x_caret-=CARET_OFFSET;
1585
caret_done = True;
1586
}
1587
}
1588
pos += len_disp;
1589
x_pos += rect.width;
1590
}
1591
if (caret_done)
1592
draw_caret(statusWindow, statusWindow->fgGC, x_caret);
1593
}
1594
}
1595
1596
/* calc required status window size and resize the window */
1597
static void align_status(StatusWindow *statusWindow)
1598
{
1599
int len_st, len_pe = 0;
1600
XRectangle rect_st, rect_pe, ink;
1601
Dimension cur_w;
1602
int value_make = CWX|CWWidth|CWHeight;
1603
XWindowChanges xwc;
1604
1605
if (NULL == statusWindow) return;
1606
if ((len_st = st_wcslen(statusWindow->status)) == 0
1607
&& (statusWindow->peText == NULL || st_wcslen(statusWindow->peText) == 0 ))
1608
return;
1609
1610
rect_pe.x = rect_pe.y = rect_pe.width = rect_pe.height = 0;
1611
1612
XwcTextExtents(statusWindow->fontset,
1613
statusWindow->status,
1614
len_st, &ink, &rect_st);
1615
if (statusWindow->peText != NULL
1616
&& (len_pe = (int32_t)wcslen(statusWindow->peText)) > 0) {
1617
XwcTextExtents(statusWindow->fontset,
1618
statusWindow->peText,
1619
len_pe, &ink, &rect_pe);
1620
}
1621
statusWindow->fOff = max(-rect_st.y, -rect_pe.y);
1622
statusWindow->fBot = max(rect_st.height, rect_pe.height);
1623
statusWindow->statusW =rect_st.width;
1624
if (rect_st.width > 0) statusWindow->statusW += BORDER_MARGIN;
1625
statusWindow->peTextW = rect_pe.width;
1626
1627
xwc.x = statusWindow->x - statusWindow->off_x;
1628
if (xwc.x < 0 ) xwc.x = 0;
1629
1630
if (len_pe > 0) {
1631
xwc.width = statusWindow->statusW
1632
+ statusWindow->peTextW + BORDER_MARGIN + 1;
1633
xwc.height = statusWindow->fBot + BORDER_MARGIN;
1634
} else {
1635
xwc.width = statusWindow->statusW;
1636
xwc.height = statusWindow->fBot + BORDER_MARGIN;
1637
}
1638
if (xwc.x + xwc.width > statusWindow->rootW){
1639
xwc.x = statusWindow->rootW - xwc.width;
1640
}
1641
XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
1642
}
1643
1644
static void shrink_status(StatusWindow *statusWindow)
1645
{
1646
int value_make = CWX|CWWidth|CWHeight;
1647
XWindowChanges xwc;
1648
1649
if (NULL == statusWindow) return;
1650
xwc.width = statusWindow->statusW;
1651
xwc.height = statusWindow->statusH;
1652
statusWindow->peTextW = 0;
1653
xwc.x = statusWindow->x - statusWindow->off_x;
1654
if (xwc.x < 0 ) xwc.x = 0;
1655
if (xwc.x + xwc.width > statusWindow->rootW){
1656
xwc.x = statusWindow->rootW - xwc.width;
1657
}
1658
XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
1659
}
1660
1661
static Bool isNativeIm()
1662
{
1663
#define XIMMODIFIER "@im="
1664
#define XIM_SERVER_CATEGORY "@server="
1665
char *immodifiers;
1666
char *imserver, *imserverPtr;
1667
Atom imserverAtom;
1668
1669
if (!(immodifiers = getenv("XMODIFIERS"))) return True;
1670
if (!(imserver = calloc(1,strlen(immodifiers)+strlen(XIM_SERVER_CATEGORY)+1))) return True;
1671
if (!(immodifiers = strstr(immodifiers,XIMMODIFIER))) return True;
1672
immodifiers += strlen(XIMMODIFIER);
1673
strcpy(imserver,XIM_SERVER_CATEGORY);
1674
imserverPtr = imserver + strlen(imserver);
1675
while(*immodifiers != '@' && *immodifiers != '\0') {
1676
*imserverPtr = *immodifiers;
1677
imserverPtr++;
1678
immodifiers++;
1679
}
1680
imserverAtom = XInternAtom(awt_display, imserver, True);
1681
free(imserver);
1682
if (imserverAtom > 0)
1683
return False;
1684
else
1685
return True;
1686
}
1687
1688
static Window getGrandParent(Window parent)
1689
{
1690
Window containerWindow,rootWindow,tmp;
1691
Window *ignoreWindowPtr;
1692
unsigned int ignoreUnit;
1693
Window grandParent=0;
1694
XWindowAttributes xwa;
1695
Atom WM_STATE;
1696
Atom type = None;
1697
int32_t format;
1698
unsigned long nitems, after;
1699
unsigned char * data;
1700
1701
if (parent == 0) return grandParent;
1702
WM_STATE = XInternAtom(dpy, "WM_STATE", True);
1703
if (WM_STATE == None) return grandParent;
1704
1705
tmp=parent;
1706
while(XQueryTree(dpy, tmp,
1707
&rootWindow, &containerWindow,
1708
&ignoreWindowPtr, &ignoreUnit)){
1709
XFree(ignoreWindowPtr);
1710
if (containerWindow == rootWindow) break;
1711
if (XGetWindowProperty(dpy, containerWindow, WM_STATE,
1712
0, 0, False, AnyPropertyType,
1713
&type, &format, &nitems, &after, &data) == Success) {
1714
XFree(data);
1715
if (type) {
1716
XGetWindowAttributes(dpy, containerWindow, &xwa);
1717
if (FALSE == xwa.override_redirect){
1718
grandParent=containerWindow;
1719
}
1720
}
1721
}
1722
tmp=containerWindow;
1723
}
1724
return grandParent;
1725
}
1726
1727
static void moveStatusWindow(StatusWindow *statusWindow)
1728
{
1729
XWindowAttributes xwa;
1730
Window child;
1731
int x, y, width;
1732
Window target;
1733
1734
if (NULL == statusWindow) return;
1735
if (statusWindow->grandParent) {
1736
target = statusWindow->grandParent;
1737
} else {
1738
target = statusWindow->parent;
1739
}
1740
XGetWindowAttributes(dpy, target, &xwa);
1741
XTranslateCoordinates(dpy,
1742
target, xwa.root,
1743
0, 0,
1744
&x, &y,
1745
&child);
1746
if (statusWindow->x != x
1747
|| statusWindow->y != y
1748
|| statusWindow->width != xwa.width
1749
|| statusWindow->height != xwa.height){
1750
statusWindow->x = x;
1751
statusWindow->y = y;
1752
statusWindow->height = xwa.height;
1753
statusWindow->width = xwa.width;
1754
x = statusWindow->x - statusWindow->off_x;
1755
y = statusWindow->y + statusWindow->height + statusWindow->off_y;
1756
if (x < 0 ){
1757
x = 0;
1758
}
1759
if (statusWindow->peTextW > 0) {
1760
width = statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN + 1;
1761
if (x + width > statusWindow->rootW){
1762
x = statusWindow->rootW - width;
1763
}
1764
} else {
1765
if (x + statusWindow->statusW > statusWindow->rootW){
1766
x = statusWindow->rootW - statusWindow->statusW;
1767
}
1768
}
1769
if (y + statusWindow->statusH > statusWindow->rootH){
1770
y = statusWindow->rootH - statusWindow->statusH;
1771
}
1772
XMoveWindow(dpy, statusWindow->w, x, y);
1773
}
1774
}
1775
1776
static void arrange_window_stack(StatusWindow* statusWindow)
1777
{
1778
XWindowChanges xwc;
1779
int value_make = CWSibling|CWStackMode;
1780
Window root, parent, *children;
1781
unsigned int nchildren;
1782
1783
if (NULL == statusWindow) return;
1784
if (XQueryTree(dpy, statusWindow->parent,
1785
&root, &parent, &children, &nchildren)){
1786
XFree(children);
1787
xwc.sibling = parent;
1788
while(XQueryTree(dpy, xwc.sibling, &root, &parent, &children, &nchildren)) {
1789
XFree(children);
1790
if (root != parent) {
1791
xwc.sibling = parent;
1792
} else {
1793
break;
1794
}
1795
}
1796
xwc.stack_mode = Above;
1797
XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
1798
}
1799
}
1800
1801
static int count_missing_fonts(char **charset_list, int charset_count)
1802
{
1803
int i,j;
1804
if (charset_count > 0) {
1805
j=charset_count;
1806
for(i=0; i < charset_count; i++) {
1807
if ((strstr(charset_list[i], "IBM-udc")) ||
1808
(strstr(charset_list[i], "IBM-sbd")) ||
1809
(strstr(charset_list[i], "IBM-ucdTW")))
1810
j--;
1811
}
1812
return j;
1813
}
1814
else
1815
return 0;
1816
}
1817
1818
static XFontSet create_fontset_name(char * font_name, Bool force)
1819
{
1820
XFontSet fontset = NULL;
1821
char **charset_list;
1822
int charset_count;
1823
char *def_string;
1824
int missing_fonts;
1825
1826
fontset = XCreateFontSet(dpy, font_name,
1827
&charset_list, &charset_count, &def_string);
1828
if (charset_count > 0) {
1829
missing_fonts = count_missing_fonts(charset_list,
1830
charset_count);
1831
XFreeStringList(charset_list);
1832
if (fontset && (missing_fonts > 0)) {
1833
if (!force) {
1834
XFreeFontSet(dpy, fontset);
1835
fontset = NULL;
1836
}
1837
}
1838
}
1839
return fontset;
1840
}
1841
1842
static XFontSet create_fontset()
1843
{
1844
XFontSet fontset = NULL;
1845
int i;
1846
static char * fontlist[] = {
1847
"-dt-interface user-medium-r-normal-S*-*-*-*-*-*-*-*-*",
1848
"-*-*-medium-r-normal-*-14-*-*-*-c-*-*-*",
1849
"-*-*-medium-r-normal-*-14-*-*-*-m-*-*-*",
1850
"-*-*-medium-r-normal--14-0-0-0-m-*-*-*",
1851
"-monotype-sansmonowt-medium-r-normal--14-*-*-*-m-*-*-*",
1852
"-*--14-*",
1853
"-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*",
1854
"-*--16-*",
1855
"-*--17-*",
1856
"-*--18-*",
1857
"-*--19-*",
1858
"-*--20-*",
1859
"-*--24-*",
1860
NULL};
1861
1862
for (i=0; fontlist[i] != NULL && fontset==NULL; i++)
1863
fontset = create_fontset_name(fontlist[i], False);
1864
1865
if (!fontset)
1866
fprintf(stdout, "Cannot load fonts for IMF.\n");
1867
return fontset;
1868
}
1869
1870
static Window get_current_focus(XIC ic) {
1871
Window w = 0;
1872
if (ic != NULL)
1873
XGetICValues(ic, XNFocusWindow, &w, NULL);
1874
return w;
1875
}
1876
1877
JNIEXPORT jboolean JNICALL
1878
Java_sun_awt_X11_XInputMethod_openXIMNative(JNIEnv *env,
1879
jobject this,
1880
jlong display)
1881
{
1882
Bool registered;
1883
1884
AWT_LOCK();
1885
1886
dpy = (Display *)jlong_to_ptr(display);
1887
1888
if (X11im == NULL) {
1889
X11im = XOpenIM(dpy, NULL, NULL, NULL);
1890
}
1891
1892
AWT_UNLOCK();
1893
1894
return JNI_TRUE;
1895
}
1896
1897
JNIEXPORT jboolean JNICALL
1898
Java_sun_awt_X11_XInputMethod_createXICNative(JNIEnv *env,
1899
jobject this,
1900
jlong window)
1901
{
1902
X11InputMethodData *pX11IMData;
1903
jobject globalRef;
1904
XIC ic;
1905
1906
AWT_LOCK();
1907
1908
if (!window) {
1909
JNU_ThrowNullPointerException(env, "NullPointerException");
1910
AWT_UNLOCK();
1911
return JNI_FALSE;
1912
}
1913
1914
pX11IMData = (X11InputMethodData *) calloc(1, sizeof(X11InputMethodData));
1915
if (pX11IMData == NULL) {
1916
THROW_OUT_OF_MEMORY_ERROR();
1917
AWT_UNLOCK();
1918
return JNI_FALSE;
1919
}
1920
1921
globalRef = (*env)->NewGlobalRef(env, this);
1922
pX11IMData->x11inputmethod = globalRef;
1923
pX11IMData->statusWindow = NULL;
1924
1925
setX11InputMethodData(env, this, pX11IMData);
1926
1927
if (createXIC(env, pX11IMData, (Window)window) == False) {
1928
destroyX11InputMethodData((JNIEnv *) NULL, pX11IMData);
1929
pX11IMData = (X11InputMethodData *) NULL;
1930
setX11InputMethodData(env, this, pX11IMData);
1931
if ((*env)->ExceptionCheck(env)) {
1932
goto finally;
1933
}
1934
}
1935
1936
finally:
1937
AWT_UNLOCK();
1938
return (pX11IMData != NULL);
1939
}
1940
1941
JNIEXPORT void JNICALL
1942
Java_sun_awt_X11_XInputMethod_setXICFocusNative(JNIEnv *env,
1943
jobject this,
1944
jlong w,
1945
jboolean req,
1946
jboolean active)
1947
{
1948
X11InputMethodData *pX11IMData;
1949
AWT_LOCK();
1950
pX11IMData = getX11InputMethodData(env, this);
1951
if (pX11IMData == NULL) {
1952
AWT_UNLOCK();
1953
return;
1954
}
1955
1956
if (req) {
1957
if (!w) {
1958
AWT_UNLOCK();
1959
return;
1960
}
1961
pX11IMData->isActiveClient = active;
1962
pX11IMData->current_ic = active ?
1963
pX11IMData->ic_active : pX11IMData->ic_passive;
1964
/*
1965
* On Solaris2.6, setXICWindowFocus() has to be invoked
1966
* before setting focus.
1967
*/
1968
get_current_focus(pX11IMData->current_ic); /* workaround for kinput2 and SCIM */
1969
if (currentFocusWindow != w) {
1970
setXICWindowFocus(pX11IMData->current_ic, w);
1971
setXICFocus(pX11IMData->current_ic, req);
1972
currentX11InputMethodInstance = pX11IMData->x11inputmethod;
1973
currentFocusWindow = w;
1974
} else {
1975
setXICFocus(pX11IMData->current_ic, req);
1976
}
1977
if ((active || pX11IMData->passiveStatusWindow)
1978
&& (pX11IMData->statusWindow && pX11IMData->statusWindow->on))
1979
onoffStatusWindow(pX11IMData, w, True);
1980
} else {
1981
currentX11InputMethodInstance = NULL;
1982
currentFocusWindow = 0;
1983
onoffStatusWindow(pX11IMData, 0, False);
1984
if (pX11IMData->current_ic != NULL)
1985
setXICFocus(pX11IMData->current_ic, req);
1986
1987
pX11IMData->current_ic = (XIC)0;
1988
}
1989
1990
XFlush(dpy);
1991
AWT_UNLOCK();
1992
}
1993
1994
/*
1995
* Class: sun_awt_X11InputMethodBase
1996
* Method: initIDs
1997
* Signature: ()V
1998
* This function gets called from the static initializer for
1999
* X11InputMethod.java to initialize the fieldIDs for fields
2000
* that may be accessed from C
2001
*/
2002
JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_initIDs
2003
(JNIEnv *env, jclass cls)
2004
{
2005
x11InputMethodIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J");
2006
}
2007
2008
/*
2009
* Class: sun_awt_X11InputMethodBase
2010
* Method: turnoffStatusWindow
2011
* Signature: ()V
2012
*/
2013
JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_turnoffStatusWindow
2014
(JNIEnv *env, jobject this)
2015
{
2016
X11InputMethodData *pX11IMData;
2017
StatusWindow *statusWindow;
2018
2019
AWT_LOCK();
2020
2021
if (NULL == currentX11InputMethodInstance
2022
|| NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))
2023
|| NULL == (statusWindow = pX11IMData->statusWindow)
2024
|| !statusWindow->on ){
2025
AWT_UNLOCK();
2026
return;
2027
}
2028
onoffStatusWindow(pX11IMData, 0, False);
2029
statusWindow->on = False;
2030
2031
AWT_UNLOCK();
2032
}
2033
2034
/*
2035
* Class: sun_awt_X11InputMethodBase
2036
* Method: disposeXIC
2037
* Signature: ()V
2038
*/
2039
JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_disposeXIC
2040
(JNIEnv *env, jobject this)
2041
{
2042
X11InputMethodData *pX11IMData = NULL;
2043
2044
AWT_LOCK();
2045
pX11IMData = getX11InputMethodData(env, this);
2046
if (pX11IMData == NULL) {
2047
AWT_UNLOCK();
2048
return;
2049
}
2050
2051
setX11InputMethodData(env, this, NULL);
2052
2053
if (pX11IMData->x11inputmethod == currentX11InputMethodInstance) {
2054
currentX11InputMethodInstance = NULL;
2055
currentFocusWindow = 0;
2056
}
2057
destroyX11InputMethodData(env, pX11IMData);
2058
AWT_UNLOCK();
2059
}
2060
2061
/*
2062
* Class: sun_awt_X11InputMethodBase
2063
* Method: resetXIC
2064
* Signature: ()Ljava/lang/String;
2065
*/
2066
JNIEXPORT jstring JNICALL Java_sun_awt_X11InputMethodBase_resetXIC
2067
(JNIEnv *env, jobject this)
2068
{
2069
X11InputMethodData *pX11IMData;
2070
char *xText = NULL;
2071
jstring jText = (jstring)0;
2072
2073
AWT_LOCK();
2074
pX11IMData = getX11InputMethodData(env, this);
2075
if (pX11IMData == NULL) {
2076
AWT_UNLOCK();
2077
return jText;
2078
}
2079
2080
if (pX11IMData->current_ic) {
2081
if (!isPreeditStateActive(pX11IMData->current_ic)) {
2082
xText = NULL;
2083
} else {
2084
if (!(pX11IMData->forceReset))
2085
setXICFocus(pX11IMData->current_ic, FALSE);
2086
xText = XmbResetIC(pX11IMData->current_ic);
2087
if (!(pX11IMData->forceReset))
2088
setXICFocus(pX11IMData->current_ic, TRUE);
2089
}
2090
} else {
2091
/*
2092
* If there is no reference to the current XIC, try to reset both XICs.
2093
*/
2094
if (!isPreeditStateActive(pX11IMData->ic_active))
2095
xText = NULL;
2096
else
2097
xText = XmbResetIC(pX11IMData->ic_active);
2098
/*it may also means that the real client component does
2099
not have focus -- has been deactivated... its xic should
2100
not have the focus, bug#4284651 showes reset XIC for htt
2101
may bring the focus back, so de-focus it again.
2102
*/
2103
setXICFocus(pX11IMData->ic_active, FALSE);
2104
if (pX11IMData->ic_active != pX11IMData->ic_passive) {
2105
char *tmpText;
2106
if (!isPreeditStateActive(pX11IMData->ic_passive))
2107
tmpText = NULL;
2108
else
2109
tmpText = XmbResetIC(pX11IMData->ic_passive);
2110
setXICFocus(pX11IMData->ic_passive, FALSE);
2111
if (xText == (char *)NULL && tmpText)
2112
xText = tmpText;
2113
}
2114
}
2115
if (xText != NULL) {
2116
jText = JNU_NewStringPlatform(env, (const char *)xText);
2117
XFree((void *)xText);
2118
}
2119
2120
/* workaround
2121
* Some IME do not call PreeditDoneCallback routine even
2122
* when XmbResetIC is called. I force to reset the preedit string.
2123
*/
2124
if (!pX11IMData->isActiveClient) {
2125
resetPassivePreeditText(pX11IMData->statusWindow);
2126
shrink_status(pX11IMData->statusWindow);
2127
} else {
2128
JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
2129
"clearComposedText",
2130
"()V");
2131
if ((*env)->ExceptionOccurred(env)) {
2132
(*env)->ExceptionDescribe(env);
2133
(*env)->ExceptionClear(env);
2134
}
2135
}
2136
2137
AWT_UNLOCK();
2138
return jText;
2139
}
2140
2141
/*
2142
* Class: sun_awt_X11InputMethodBase
2143
* Method: setCompositionEnabledNative
2144
* Signature: (Z)Z
2145
*
2146
* This method tries to set the XNPreeditState attribute associated with the current
2147
* XIC to the passed in 'enable' state.
2148
*
2149
* Return JNI_TRUE if XNPreeditState attribute is successfully changed to the
2150
* 'enable' state; Otherwise, if XSetICValues fails to set this attribute,
2151
* java.lang.UnsupportedOperationException will be thrown. JNI_FALSE is returned if this
2152
* method fails due to other reasons.
2153
*/
2154
JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_setCompositionEnabledNative
2155
(JNIEnv *env, jobject this, jboolean enable)
2156
{
2157
X11InputMethodData *pX11IMData;
2158
char * ret = NULL;
2159
XVaNestedList pr_atrb;
2160
2161
AWT_LOCK();
2162
pX11IMData = getX11InputMethodData(env, this);
2163
2164
if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) {
2165
AWT_UNLOCK();
2166
return JNI_FALSE;
2167
}
2168
2169
pr_atrb = XVaCreateNestedList(0, XNPreeditState,
2170
(enable ? XIMPreeditEnable : XIMPreeditDisable), NULL);
2171
ret = XSetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL);
2172
XFree((void *)pr_atrb);
2173
AWT_UNLOCK();
2174
2175
if ((ret != 0) &&
2176
((strcmp(ret, XNPreeditAttributes) == 0)
2177
|| (strcmp(ret, XNPreeditState) == 0))) {
2178
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");
2179
}
2180
2181
return (jboolean)(ret == 0);
2182
}
2183
2184
/*
2185
* Class: sun_awt_X11InputMethodBase
2186
* Method: isCompositionEnabledNative
2187
* Signature: ()Z
2188
*
2189
* This method tries to get the XNPreeditState attribute associated with the current XIC.
2190
*
2191
* Return JNI_TRUE if the XNPreeditState is successfully retrieved. Otherwise, if
2192
* XGetICValues fails to get this attribute, java.lang.UnsupportedOperationException
2193
* will be thrown. JNI_FALSE is returned if this method fails due to other reasons.
2194
*/
2195
JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_isCompositionEnabledNative
2196
(JNIEnv *env, jobject this)
2197
{
2198
X11InputMethodData *pX11IMData = NULL;
2199
char * ret = NULL;
2200
XIMPreeditState state = XIMPreeditUnKnown;
2201
XVaNestedList pr_atrb;
2202
2203
AWT_LOCK();
2204
pX11IMData = getX11InputMethodData(env, this);
2205
2206
if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) {
2207
AWT_UNLOCK();
2208
return JNI_FALSE;
2209
}
2210
2211
pr_atrb = XVaCreateNestedList(0, XNPreeditState, &state, NULL);
2212
ret = XGetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL);
2213
XFree((void *)pr_atrb);
2214
AWT_UNLOCK();
2215
2216
if ((ret != 0) &&
2217
((strcmp(ret, XNPreeditAttributes) == 0)
2218
|| (strcmp(ret, XNPreeditState) == 0))) {
2219
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");
2220
return JNI_FALSE;
2221
}
2222
2223
return (jboolean)(state == XIMPreeditEnable);
2224
}
2225
2226
JNIEXPORT void JNICALL Java_sun_awt_X11_XInputMethod_adjustStatusWindow
2227
(JNIEnv *env, jobject this, jlong window)
2228
{
2229
2230
}
2231
2232
/*
2233
* Class: sun_awt_X11InputMethod
2234
* Method: setStatusAreaVisible
2235
* Signature: (ZJ)V
2236
*/
2237
JNIEXPORT void JNICALL Java_sun_awt_X11InputMethod_setStatusAreaVisible
2238
(JNIEnv *env, jobject this, jboolean value, jlong data)
2239
{
2240
X11InputMethodData *pX11IMData;
2241
2242
pX11IMData = getX11InputMethodData(env, this);
2243
if (NULL == pX11IMData) return;
2244
if (NULL == pX11IMData->statusWindow) return;
2245
2246
if ((int)value){
2247
pX11IMData->statusWindow->on = True;
2248
}else{
2249
pX11IMData->statusWindow->on = False;
2250
}
2251
return;
2252
}
2253
2254