8213232: Unix/X11 setCompositionEnableNative issue
authoritakiguchi
Tue, 30 Apr 2019 14:30:17 -0700
changeset 54867 65297f60ba19
parent 54866 a7a436e080c1
child 54868 88b769ae99c7
8213232: Unix/X11 setCompositionEnableNative issue Reviewed-by: serb
src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c
src/java.desktop/share/classes/sun/awt/im/InputContext.java
src/java.desktop/unix/classes/sun/awt/X11InputMethod.java
src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c
--- a/src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c	Tue Apr 30 04:15:31 2019 -0700
+++ b/src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c	Tue Apr 30 14:30:17 2019 -0700
@@ -88,7 +88,7 @@
  * values above.
  */
 static XIMProc callback_funcs[NCALLBACKS] = {
-    (XIMProc)PreeditStartCallback,
+    (XIMProc)(void *)&PreeditStartCallback,
     (XIMProc)PreeditDoneCallback,
     (XIMProc)PreeditDrawCallback,
     (XIMProc)PreeditCaretCallback,
--- a/src/java.desktop/share/classes/sun/awt/im/InputContext.java	Tue Apr 30 04:15:31 2019 -0700
+++ b/src/java.desktop/share/classes/sun/awt/im/InputContext.java	Tue Apr 30 14:30:17 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -547,6 +547,8 @@
                 if (inputMethod instanceof InputMethodAdapter) {
                     ((InputMethodAdapter) inputMethod).setClientComponent(null);
                 }
+                if (null == currentClientComponent.getInputMethodRequests())
+                    wasCompositionEnabledSupported = false;
             }
             savedLocale = inputMethod.getLocale();
 
@@ -563,6 +565,7 @@
             enableClientWindowNotification(inputMethod, false);
             if (this == inputMethodWindowContext) {
                 inputMethod.hideWindows();
+                inputMethod.removeNotify();
                 inputMethodWindowContext = null;
             }
             inputMethodLocator = null;
--- a/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java	Tue Apr 30 04:15:31 2019 -0700
+++ b/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java	Tue Apr 30 14:30:17 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -55,7 +55,7 @@
      * Reset the composition state to the current composition state.
      */
     protected void resetCompositionState() {
-        if (compositionEnableSupported) {
+        if (compositionEnableSupported && haveActiveClient()) {
             try {
                 /* Restore the composition mode to the last saved composition
                    mode. */
--- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c	Tue Apr 30 04:15:31 2019 -0700
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c	Tue Apr 30 14:30:17 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -46,7 +46,7 @@
   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 *);
@@ -80,7 +80,7 @@
  * values above.
  */
 static XIMProc callback_funcs[NCALLBACKS] = {
-    (XIMProc)PreeditStartCallback,
+    (XIMProc)(void *)&PreeditStartCallback,
     (XIMProc)PreeditDoneCallback,
     (XIMProc)PreeditDrawCallback,
     (XIMProc)PreeditCaretCallback,
@@ -175,6 +175,9 @@
 static void setX11InputMethodData(JNIEnv *, jobject, X11InputMethodData *);
 static void destroyX11InputMethodData(JNIEnv *, X11InputMethodData *);
 static void freeX11InputMethodData(JNIEnv *, X11InputMethodData *);
+#if defined(__linux__) || defined(MACOSX)
+static Window getParentWindow(Window);
+#endif
 
 #ifdef __solaris__
 /* Prototype for this function is missing in Solaris X11R6 Xlib.h */
@@ -1019,9 +1022,28 @@
         }
     }
 
+    // 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, XIMInitialState,
+                     NULL);
+    if (pX11IMData->ic_passive != 0
+            && pX11IMData->ic_active != pX11IMData->ic_passive)
+        XSetICValues(pX11IMData->ic_passive,
+                     XNResetState, XIMInitialState,
+                     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:
@@ -1031,11 +1053,12 @@
     return False;
 }
 
-static void
+static int
 PreeditStartCallback(XIC ic, XPointer client_data, XPointer call_data)
 {
     /*ARGSUSED*/
     /* printf("Native: PreeditStartCallback\n"); */
+    return -1;
 }
 
 static void
@@ -1163,6 +1186,29 @@
 {
     /*ARGSUSED*/
     /*printf("StatusDoneCallback:\n"); */
+    JNIEnv *env = GetJNIEnv();
+    X11InputMethodData *pX11IMData = NULL;
+    StatusWindow *statusWindow;
+
+    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;
+
+    onoffStatusWindow(pX11IMData, 0, False);
+
+ finally:
+    AWT_UNLOCK();
 }
 
 static void
@@ -1552,6 +1598,10 @@
 {
     X11InputMethodData *pX11IMData;
     char * ret = NULL;
+    XVaNestedList   pr_atrb;
+#if defined(__linux__) || defined(MACOSX)
+    Boolean calledXSetICFocus = False;
+#endif
 
     AWT_LOCK();
     pX11IMData = getX11InputMethodData(env, this);
@@ -1561,11 +1611,44 @@
         return JNI_FALSE;
     }
 
-    ret = XSetICValues(pX11IMData->current_ic, XNPreeditState,
-                       (enable ? XIMPreeditEnable : XIMPreeditDisable), NULL);
+#if defined(__linux__) || defined(MACOSX)
+    if (NULL != pX11IMData->statusWindow) {
+        Window focus = 0;
+        int revert_to;
+#if defined(_LP64) && !defined(_LITTLE_ENDIAN)
+        // The Window value which is used for XGetICValues must be 32bit on BigEndian XOrg's xlib
+        unsigned int w = 0;
+#else
+        Window w = 0;
+#endif
+        XGetInputFocus(awt_display, &focus, &revert_to);
+        XGetICValues(pX11IMData->current_ic, XNFocusWindow, &w, NULL);
+        if (RevertToPointerRoot == revert_to
+                && pX11IMData->ic_active != pX11IMData->ic_passive) {
+            if (pX11IMData->current_ic == pX11IMData->ic_active) {
+                if (getParentWindow(focus) == getParentWindow(w)) {
+                    XUnsetICFocus(pX11IMData->ic_active);
+                    calledXSetICFocus = True;
+                }
+            }
+        }
+    }
+#endif
+    pr_atrb = XVaCreateNestedList(0,
+                  XNPreeditState, (enable ? XIMPreeditEnable : XIMPreeditDisable),
+                  NULL);
+    ret = XSetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL);
+    XFree((void *)pr_atrb);
+#if defined(__linux__) || defined(MACOSX)
+    if (calledXSetICFocus) {
+        XSetICFocus(pX11IMData->ic_active);
+    }
+#endif
     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", "");
     }
 
@@ -1588,7 +1671,14 @@
 {
     X11InputMethodData *pX11IMData = NULL;
     char * ret = NULL;
-    XIMPreeditState state;
+#if defined(_LP64) && !defined(_LITTLE_ENDIAN)
+    // XIMPreeditState value which is used for XGetICValues must be 32bit on BigEndian XOrg's xlib
+    unsigned int state = XIMPreeditUnKnown;
+#else
+    XIMPreeditState state = XIMPreeditUnKnown;
+#endif
+
+    XVaNestedList   pr_atrb;
 
     AWT_LOCK();
     pX11IMData = getX11InputMethodData(env, this);
@@ -1598,10 +1688,14 @@
         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;
     }
@@ -1618,3 +1712,20 @@
     AWT_UNLOCK();
 #endif
 }
+
+#if defined(__linux__) || defined(MACOSX)
+static Window getParentWindow(Window w)
+{
+    Window root=None, parent=None, *ignore_children=NULL;
+    unsigned int ignore_uint=0;
+    Status status = 0;
+
+    if (w == None)
+        return None;
+    status = XQueryTree(dpy, w, &root, &parent, &ignore_children, &ignore_uint);
+    XFree(ignore_children);
+    if (status == 0)
+        return None;
+    return parent;
+}
+#endif