diff --git a/src/x11_init.c b/src/x11_init.c index 2031016f..2fbde908 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -440,13 +440,18 @@ static GLFWbool hasUsableInputMethodStyle(void) { GLFWbool found = GLFW_FALSE; XIMStyles* styles = NULL; + const char* imStyle = getenv("IM_STYLE"); if (XGetIMValues(_glfw.x11.im, XNQueryInputStyle, &styles, NULL) != NULL) return GLFW_FALSE; + _glfw.x11.imStyle = STYLE_OVERTHESPOT; + if (imStyle && strcmp(imStyle, "on-the-spot") == 0) + _glfw.x11.imStyle = STYLE_ONTHESPOT; + for (unsigned int i = 0; i < styles->count_styles; i++) { - if (styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing)) + if (styles->supported_styles[i] == _glfw.x11.imStyle) { found = GLFW_TRUE; break; diff --git a/src/x11_platform.h b/src/x11_platform.h index 33ca3ba8..2bd88744 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -91,6 +91,9 @@ #define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098 #define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3 +#define STYLE_OVERTHESPOT (XIMPreeditNothing | XIMStatusNothing) +#define STYLE_ONTHESPOT (XIMPreeditCallbacks | XIMStatusCallbacks) + typedef XID GLXWindow; typedef XID GLXDrawable; typedef struct __GLXFBConfig* GLXFBConfig; @@ -584,6 +587,8 @@ typedef struct _GLFWlibraryX11 XContext context; // XIM input method XIM im; + // XIM input method style + XIMStyle imStyle; // Most recent error code received by X error handler int errorCode; // Primary selection string (while the primary selection is owned) diff --git a/src/x11_window.c b/src/x11_window.c index d7603a82..f20c2af4 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -1461,6 +1461,11 @@ static void processEvent(XEvent *event) if (chars != buffer) _glfw_free(chars); + + // In the case of over-the-spot, need to update the position here + // because preedit-callbacks can not be used. + if (_glfw.x11.imStyle == STYLE_OVERTHESPOT) + _ximChangeCursorPosition(window->x11.ic, window); } } else @@ -2085,28 +2090,54 @@ void _glfwCreateInputContextX11(_GLFWwindow* window) XIMCallback callback; callback.callback = (XIMProc) inputContextDestroyCallback; callback.client_data = (XPointer) window; - XVaNestedList preeditList = _createXIMPreeditCallbacks(window); - XVaNestedList statusList = _createXIMStatusCallbacks(window); - window->x11.ic = XCreateIC(_glfw.x11.im, - XNInputStyle, - XIMPreeditCallbacks | XIMStatusCallbacks, - XNClientWindow, - window->x11.handle, - XNFocusWindow, - window->x11.handle, - XNPreeditAttributes, - preeditList, - XNStatusAttributes, - statusList, - XNDestroyCallback, - &callback, - NULL); - - XFree(preeditList); - XFree(statusList); window->x11.imeFocus = GLFW_FALSE; + if (_glfw.x11.imStyle == STYLE_ONTHESPOT) + { + XVaNestedList preeditList = _createXIMPreeditCallbacks(window); + XVaNestedList statusList = _createXIMStatusCallbacks(window); + + window->x11.ic = XCreateIC(_glfw.x11.im, + XNInputStyle, + _glfw.x11.imStyle, + XNClientWindow, + window->x11.handle, + XNFocusWindow, + window->x11.handle, + XNPreeditAttributes, + preeditList, + XNStatusAttributes, + statusList, + XNDestroyCallback, + &callback, + NULL); + + XFree(preeditList); + XFree(statusList); + } + else if (_glfw.x11.imStyle == STYLE_OVERTHESPOT) + { + window->x11.ic = XCreateIC(_glfw.x11.im, + XNInputStyle, + _glfw.x11.imStyle, + XNClientWindow, + window->x11.handle, + XNFocusWindow, + window->x11.handle, + XNDestroyCallback, + &callback, + NULL); + } + else + { + // (XIMPreeditNothing | XIMStatusNothing) is considered as STYLE_OVERTHESPOT. + // So this branch should not be used now. + _glfwInputError(GLFW_PLATFORM_ERROR, + "X11: Failed to create input context."); + return; + } + if (window->x11.ic) { XWindowAttributes attribs; @@ -3435,6 +3466,10 @@ void _glfwPlatformResetPreeditText(_GLFWwindow* window) XVaNestedList preedit_attr; char* result; + // Can not manage IME in the case of over-the-spot. + if (_glfw.x11.imStyle == STYLE_OVERTHESPOT) + return; + if (window->ntext == 0) return; @@ -3458,6 +3493,11 @@ void _glfwPlatformResetPreeditText(_GLFWwindow* window) void _glfwPlatformSetIMEStatus(_GLFWwindow* window, int active) { XIC ic = window->x11.ic; + + // Can not manage IME in the case of over-the-spot. + if (_glfw.x11.imStyle == STYLE_OVERTHESPOT) + return; + if (active) XSetICFocus(ic); else @@ -3466,6 +3506,10 @@ void _glfwPlatformSetIMEStatus(_GLFWwindow* window, int active) int _glfwPlatformGetIMEStatus(_GLFWwindow* window) { + // Can not manage IME in the case of over-the-spot. + if (_glfw.x11.imStyle == STYLE_OVERTHESPOT) + return GLFW_FALSE; + return window->x11.imeFocus; }