X11: Change default style to over-the-spot

In over-the-spot mode, almost all APIs are disabled.
Applications only need to specify the candidate window position by
`glfwSetPreeditCursorPos`.

We can change style to on-the-spot by setting "on-the-spot" to the
environmental variable `IM_STYLE`.

However on-the-spot mode of X11 has the following problems:

* Status APIs don't work because status callbacks don't work
  (at least in my ibus environment)
* Can't specify the candidate window position
This commit is contained in:
Daijiro Fukuda 2022-04-26 18:24:57 +09:00
parent a5a3cbe5c0
commit 28ea48ea38
3 changed files with 74 additions and 20 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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;
}