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