From 1c7e52faf889fb2a1fb2c1392953df295ed6b84a Mon Sep 17 00:00:00 2001 From: Daijiro Fukuda Date: Fri, 20 May 2022 17:26:25 +0900 Subject: [PATCH] Enable glfwSetPreeditCursorPos API to apply the change immediately In Windows and X11, the changes were applied at the time of the preedit callback. This has been removed and make them applied immediately. In macOS, the position callback is provided, so do nothing and leave this to it. --- src/cocoa_init.m | 1 + src/cocoa_platform.h | 1 + src/cocoa_window.m | 6 +++++ src/input.c | 8 +++++++ src/internal.h | 1 + src/null_init.c | 1 + src/null_platform.h | 1 + src/null_window.c | 4 ++++ src/win32_init.c | 1 + src/win32_platform.h | 1 + src/win32_window.c | 26 ++++++++++++--------- src/wl_init.c | 1 + src/wl_platform.h | 1 + src/wl_window.c | 4 ++++ src/x11_init.c | 1 + src/x11_platform.h | 1 + src/x11_window.c | 54 ++++++++++++++++++++------------------------ 17 files changed, 72 insertions(+), 41 deletions(-) diff --git a/src/cocoa_init.m b/src/cocoa_init.m index e547859f..196b2b10 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -500,6 +500,7 @@ GLFWbool _glfwConnectCocoa(int platformID, _GLFWplatform* platform) _glfwGetKeyScancodeCocoa, _glfwSetClipboardStringCocoa, _glfwGetClipboardStringCocoa, + _glfwUpdatePreeditCursorPosCocoa, _glfwResetPreeditTextCocoa, _glfwSetIMEStatusCocoa, _glfwGetIMEStatusCocoa, diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index 9361de93..397444f3 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -268,6 +268,7 @@ void _glfwSetCursorCocoa(_GLFWwindow* window, _GLFWcursor* cursor); void _glfwSetClipboardStringCocoa(const char* string); const char* _glfwGetClipboardStringCocoa(void); +void _glfwUpdatePreeditCursorPosCocoa(_GLFWwindow* window); void _glfwResetPreeditTextCocoa(_GLFWwindow* window); void _glfwSetIMEStatusCocoa(_GLFWwindow* window, int active); int _glfwGetIMEStatusCocoa(_GLFWwindow* window); diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 33576d65..40d51588 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1858,6 +1858,12 @@ const char* _glfwGetClipboardStringCocoa(void) } // autoreleasepool } +void _glfwUpdatePreeditCursorPosCocoa(_GLFWwindow* window) +{ + // Do nothing. Instead, implement `firstRectForCharacterRange` callback + // to update the position. +} + void _glfwResetPreeditTextCocoa(_GLFWwindow* window) { NSTextInputContext* context = [NSTextInputContext currentInputContext]; diff --git a/src/input.c b/src/input.c index cbd15330..704913e5 100644 --- a/src/input.c +++ b/src/input.c @@ -907,9 +907,17 @@ GLFWAPI void glfwGetPreeditCursorPos(GLFWwindow* handle, int *x, int *y, int *h) GLFWAPI void glfwSetPreeditCursorPos(GLFWwindow* handle, int x, int y, int h) { _GLFWwindow* window = (_GLFWwindow*) handle; + + if (x == window->preeditCursorPosX && + y == window->preeditCursorPosY && + h == window->preeditCursorHeight) + return; + window->preeditCursorPosX = x; window->preeditCursorPosY = y; window->preeditCursorHeight = h; + + _glfw.platform.updatePreeditCursorPos(window); } GLFWAPI void glfwResetPreeditText(GLFWwindow* handle) diff --git a/src/internal.h b/src/internal.h index b23e4b98..56d6386b 100644 --- a/src/internal.h +++ b/src/internal.h @@ -699,6 +699,7 @@ struct _GLFWplatform int (*getKeyScancode)(int); void (*setClipboardString)(const char*); const char* (*getClipboardString)(void); + void (*updatePreeditCursorPos)(_GLFWwindow*); void (*resetPreeditText)(_GLFWwindow*); void (*setIMEStatus)(_GLFWwindow*,int); int (*getIMEStatus)(_GLFWwindow*); diff --git a/src/null_init.c b/src/null_init.c index b5b9beec..f26dfab7 100644 --- a/src/null_init.c +++ b/src/null_init.c @@ -56,6 +56,7 @@ GLFWbool _glfwConnectNull(int platformID, _GLFWplatform* platform) _glfwGetKeyScancodeNull, _glfwSetClipboardStringNull, _glfwGetClipboardStringNull, + _glfwUpdatePreeditCursorPosNull, _glfwResetPreeditTextNull, _glfwSetIMEStatusNull, _glfwGetIMEStatusNull, diff --git a/src/null_platform.h b/src/null_platform.h index 9c439a2d..dca17d07 100644 --- a/src/null_platform.h +++ b/src/null_platform.h @@ -137,6 +137,7 @@ const char* _glfwGetClipboardStringNull(void); const char* _glfwGetScancodeNameNull(int scancode); int _glfwGetKeyScancodeNull(int key); +void _glfwUpdatePreeditCursorPosNull(_GLFWwindow* window); void _glfwResetPreeditTextNull(_GLFWwindow* window); void _glfwSetIMEStatusNull(_GLFWwindow* window, int active); int _glfwGetIMEStatusNull(_GLFWwindow* window); diff --git a/src/null_window.c b/src/null_window.c index a1ae6e9d..9c092154 100644 --- a/src/null_window.c +++ b/src/null_window.c @@ -542,6 +542,10 @@ const char* _glfwGetClipboardStringNull(void) return _glfw.null.clipboardString; } +void _glfwUpdatePreeditCursorPosNull(_GLFWwindow* window) +{ +} + void _glfwResetPreeditTextNull(_GLFWwindow* window) { } diff --git a/src/win32_init.c b/src/win32_init.c index 62821932..03b8e934 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -596,6 +596,7 @@ GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform) _glfwGetKeyScancodeWin32, _glfwSetClipboardStringWin32, _glfwGetClipboardStringWin32, + _glfwUpdatePreeditCursorPosWin32, _glfwResetPreeditTextWin32, _glfwSetIMEStatusWin32, _glfwGetIMEStatusWin32, diff --git a/src/win32_platform.h b/src/win32_platform.h index 81f18477..9bd08d68 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -629,6 +629,7 @@ void _glfwSetCursorWin32(_GLFWwindow* window, _GLFWcursor* cursor); void _glfwSetClipboardStringWin32(const char* string); const char* _glfwGetClipboardStringWin32(void); +void _glfwUpdatePreeditCursorPosWin32(_GLFWwindow* window); void _glfwResetPreeditTextWin32(_GLFWwindow* window); void _glfwSetIMEStatusWin32(_GLFWwindow* window, int active); int _glfwGetIMEStatusWin32(_GLFWwindow* window); diff --git a/src/win32_window.c b/src/win32_window.c index 8d355b9b..2038bc3e 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -533,16 +533,6 @@ static void maximizeWindowManually(_GLFWwindow* window) SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED); } -// Set cursor position to decide candidate window -static void _win32ChangeCursorPosition(HIMC hIMC, _GLFWwindow* window) -{ - int x = window->preeditCursorPosX; - int y = window->preeditCursorPosY; - int h = window->preeditCursorHeight; - CANDIDATEFORM excludeRect = { 0, CFS_EXCLUDE, { x, y }, { x, y, x, y + h } }; - ImmSetCandidateWindow(hIMC, &excludeRect); -} - static GLFWbool getImmPreedit(_GLFWwindow* window) { HIMC hIMC = ImmGetContext(window->win32.handle); @@ -628,7 +618,6 @@ static GLFWbool getImmPreedit(_GLFWwindow* window) _glfw_free(clauses); _glfwInputPreedit(window, focusedBlock); - _win32ChangeCursorPosition(hIMC, window); } ImmReleaseContext(window->win32.handle, hIMC); @@ -2524,6 +2513,21 @@ const char* _glfwGetClipboardStringWin32(void) return _glfw.win32.clipboardString; } +void _glfwUpdatePreeditCursorPosWin32(_GLFWwindow* window) +{ + HWND hWnd = window->win32.handle; + HIMC hIMC = ImmGetContext(hWnd); + + int x = window->preeditCursorPosX; + int y = window->preeditCursorPosY; + int h = window->preeditCursorHeight; + CANDIDATEFORM excludeRect = { 0, CFS_EXCLUDE, { x, y }, { x, y, x, y + h } }; + + ImmSetCandidateWindow(hIMC, &excludeRect); + + ImmReleaseContext(hWnd, hIMC); +} + void _glfwResetPreeditTextWin32(_GLFWwindow* window) { HWND hWnd = window->win32.handle; diff --git a/src/wl_init.c b/src/wl_init.c index 7e55de56..d4a8016d 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -362,6 +362,7 @@ GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform) _glfwGetKeyScancodeWayland, _glfwSetClipboardStringWayland, _glfwGetClipboardStringWayland, + _glfwUpdatePreeditCursorPosWayland, _glfwResetPreeditTextWayland, _glfwSetIMEStatusWayland, _glfwGetIMEStatusWayland, diff --git a/src/wl_platform.h b/src/wl_platform.h index 8b7db75d..29b69f71 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -490,6 +490,7 @@ void _glfwSetCursorWayland(_GLFWwindow* window, _GLFWcursor* cursor); void _glfwSetClipboardStringWayland(const char* string); const char* _glfwGetClipboardStringWayland(void); +void _glfwUpdatePreeditCursorPosWayland(_GLFWwindow* window); void _glfwResetPreeditTextWayland(_GLFWwindow* window); void _glfwSetIMEStatusWayland(_GLFWwindow* window, int active); int _glfwGetIMEStatusWayland(_GLFWwindow* window); diff --git a/src/wl_window.c b/src/wl_window.c index b4b6dc01..3b53696f 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -2592,6 +2592,10 @@ const char* _glfwGetClipboardStringWayland(void) return _glfw.wl.clipboardString; } +void _glfwUpdatePreeditCursorPosWayland(_GLFWwindow* window) +{ +} + void _glfwResetPreeditTextWayland(_GLFWwindow* window) { } diff --git a/src/x11_init.c b/src/x11_init.c index bc53e6c4..a5e3af02 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -1184,6 +1184,7 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform) _glfwGetKeyScancodeX11, _glfwSetClipboardStringX11, _glfwGetClipboardStringX11, + _glfwUpdatePreeditCursorPosX11, _glfwResetPreeditTextX11, _glfwSetIMEStatusX11, _glfwGetIMEStatusX11, diff --git a/src/x11_platform.h b/src/x11_platform.h index 1abde8a0..7b6df7b1 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -979,6 +979,7 @@ void _glfwSetCursorX11(_GLFWwindow* window, _GLFWcursor* cursor); void _glfwSetClipboardStringX11(const char* string); const char* _glfwGetClipboardStringX11(void); +void _glfwUpdatePreeditCursorPosX11(_GLFWwindow* window); void _glfwResetPreeditTextX11(_GLFWwindow* window); void _glfwSetIMEStatusX11(_GLFWwindow* window, int active); int _glfwGetIMEStatusX11(_GLFWwindow* window); diff --git a/src/x11_window.c b/src/x11_window.c index b0c3607e..1c6229da 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -543,20 +543,6 @@ static void inputContextDestroyCallback(XIC ic, XPointer clientData, XPointer ca window->x11.ic = NULL; } -// Update cursor position to decide candidate window -// -static void _ximChangeCursorPosition(XIC xic, _GLFWwindow* window) -{ - XVaNestedList preedit_attr; - XPoint spot; - - spot.x = window->preeditCursorPosX; - spot.y = window->preeditCursorPosY + window->preeditCursorHeight; - preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL); - XSetICValues(xic, XNPreeditAttributes, preedit_attr, NULL); - XFree(preedit_attr); -} - // IME Start callback (do nothing) // static void _ximPreeditStartCallback(XIC xic, XPointer clientData, XPointer callData) @@ -581,11 +567,6 @@ static void _ximPreeditDrawCallback(XIC xic, XPointer clientData, XIMPreeditDraw XIMFeedback f; _GLFWwindow* window = (_GLFWwindow*) clientData; - // keep cursor position to reduce API call - int cursorX = window->preeditCursorPosX; - int cursorY = window->preeditCursorPosY; - int cursorHeight = window->preeditCursorHeight; - if (!callData->text) { // preedit text is empty @@ -688,12 +669,6 @@ static void _ximPreeditDrawCallback(XIC xic, XPointer clientData, XIMPreeditDraw window->preeditAttributeBlocks[3] = 0; _glfwInputPreedit(window, 1); } - if ((cursorX != window->preeditCursorPosX) || - (cursorY != window->preeditCursorPosY) || - (cursorHeight != window->preeditCursorHeight)) - { - _ximChangeCursorPosition(xic, window); - } } } @@ -1461,11 +1436,6 @@ 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 @@ -3259,6 +3229,21 @@ const char* _glfwGetClipboardStringX11(void) return getSelectionString(_glfw.x11.CLIPBOARD); } +void _glfwUpdatePreeditCursorPosX11(_GLFWwindow* window) +{ + XVaNestedList preedit_attr; + XPoint spot; + + if (!window->x11.ic) + return; + + spot.x = window->preeditCursorPosX; + spot.y = window->preeditCursorPosY + window->preeditCursorHeight; + preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL); + XSetICValues(window->x11.ic, XNPreeditAttributes, preedit_attr, NULL); + XFree(preedit_attr); +} + void _glfwResetPreeditTextX11(_GLFWwindow* window) { XIC ic = window->x11.ic; @@ -3268,6 +3253,9 @@ void _glfwResetPreeditTextX11(_GLFWwindow* window) XVaNestedList preedit_attr; char* result; + if (!ic) + return; + // Can not manage IME in the case of over-the-spot. if (_glfw.x11.imStyle == STYLE_OVERTHESPOT) return; @@ -3296,6 +3284,9 @@ void _glfwSetIMEStatusX11(_GLFWwindow* window, int active) { XIC ic = window->x11.ic; + if (!ic) + return; + // Can not manage IME in the case of over-the-spot. if (_glfw.x11.imStyle == STYLE_OVERTHESPOT) return; @@ -3308,6 +3299,9 @@ void _glfwSetIMEStatusX11(_GLFWwindow* window, int active) int _glfwGetIMEStatusX11(_GLFWwindow* window) { + if (!window->x11.ic) + return GLFW_FALSE; + // Can not manage IME in the case of over-the-spot. if (_glfw.x11.imStyle == STYLE_OVERTHESPOT) return GLFW_FALSE;