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;