diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ae748e5..ae3530cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -226,7 +226,7 @@ endif() if (_GLFW_WIN32) list(APPEND glfw_PKG_LIBS "-lgdi32") - list(APPEND glfw_LIBRARIES "imm32") + list(APPEND glfw_LIBRARIES "-limm32") if (GLFW_USE_HYBRID_HPG) set(_GLFW_USE_HYBRID_HPG 1) diff --git a/docs/input.dox b/docs/input.dox index 8b448e81..0731cd1a 100644 --- a/docs/input.dox +++ b/docs/input.dox @@ -206,35 +206,42 @@ void charmods_callback(GLFWwindow* window, unsigned int codepoint, int mods) } @endcode -@subsection preedit IME Support -All desktop operating systems support IME (Input Method Editor) to input characters -that are not mapped with physical keys. IME have been popular among Eeastern Asian people. -And some operating systems start supporting voice input via IME mechanism. +@subsection preedit IME support -GLFW provides IME support functions to help -you implement better text input features. You should add suitable visualization code for -preedit text. +All modern operating systems provide a +[IME](https://en.wikipedia.org/wiki/Input_method) (Input Method Editor) +mechanism to input character sets that cannot be mapped to physical keys, such +as [CJK characters](https://en.wikipedia.org/wiki/CJK_characters) (Chinese, +Japanese, Korean). Some operating systems also support speech-to-text input via +the IME mechanism. + +GLFW provides IME support functions to help you implement better text input +features. You should add suitable visualization code for pre-edit text. IME works in front of actual character input events (@ref input_char). -If your application uses text input and you want to support IME, -you should register preedit callback to receive preedit text before committed. +If your application uses text input and you want to support IME, you should +register pre-edit callback to receive pre-edit text before committed. @code glfwSetPreeditCallback(window, preedit_callback); @endcode -The callback function receives chunk of text and focused block information. +The callback function receives the pre-edit text and block information. @code -static void preedit_callback(GLFWwindow* window, int strLength, unsigned int* string, int blockLength, int* blocks, int focusedBlock) { +static void preedit_callback(GLFWwindow* window, unsigned int* codepoints, int blockCount, int* blocks, int focusedBlock) +{ } @endcode -strLength and string parameter reprsent whole preedit text. Each character of the preedit string is a codepoint like @ref input_char. +The codepoints parameter contains the whole pre-edit text. Each character of the +pre-edit string is a Unicode codepoint like with @ref input_char. -If you want to type the text "寿司(sushi)", Usually the callback is called several times like the following sequence: +If you want to type the text "寿司" (sushi), usually the callback is called +several times like the following sequence: +@code -# key event: s -# preedit: [string: "s", block: [1], focusedBlock: 0] -# key event: u @@ -250,52 +257,61 @@ If you want to type the text "寿司(sushi)", Usually the callback is called sev -# char: '寿' -# char: '司' -# preedit: [string: "", block: [], focusedBlock: 0] +@endcode -If preedit text includes several semantic blocks, preedit callbacks returns several blocks after a space key pressed: +If pre-edit text includes several semantic blocks, pre-edit callbacks returns +several blocks after a space key pressed: +@code -# preedit: [string: "わたしはすしをたべます", block: [11], focusedBlock: 0] -# preedit: [string: "私は寿司を食べます", block: [2, 7], focusedBlock: 1] +@endcode -"blocks" is a list of block length. The above case, it contains the following blocks and second block is focused. +"blocks" is a list of block length. The above case, it contains the following +blocks and second block is focused. +@code - 私は - [寿司を食べます] - -commited text(passed via regular @ref input_char event), unfocused block, focused block should have different text style. - - -GLFW provides helper function to teach suitable position of the candidate window to window system. -Window system decides the best position from text cursor geometry (x, y coords and height). You should call this function -in the above preedit text callback function. - -@code -glfwSetPreeditCursorPos(window, x, y, h); -glfwGetPreeditCursorPos(window, &x, &y, &h); @endcode -Sometimes IME task is interrupted by user or application. There are several functions to support these situation. -You can receive notification about IME status change(on/off) by using the following function: +committed text (passed via regular @ref input_char event), unfocused block, +focused block should have different text style. + +GLFW provides helper function to teach suitable position of the candidate window +to window system. Window system decides the best position from text cursor +geometry (window coordinates and height). You should call this function in the +above pre-edit text callback function. @code -glfwSetIMEStatusCallback(window, imestatus_callback); +int xpos, ypos, height; +glfwSetPreeditCursorPos(window, xpos, ypos, height); +glfwGetPreeditCursorPos(window, &xpos, &ypos, &height); @endcode -imestatus_callback has simple sigunature like this: +Sometimes IME task is interrupted by user or application. There are several +functions to support these situation. You can receive notification about IME +status change(on/off) by using the following function: @code -static void imestatus_callback(GLFWwindow* window) { +glfwSetIMEStatusCallback(window, ime_status_callback); +@endcode + +The ime_status_callback has simple signature like this: + +@code +static void ime_status_callback(GLFWwindow* window) +{ } @endcode -You can implement the code that resets or commits preedit text when IME status is changed and preedit text is not empty. +You can implement the code that resets or commits pre-edit text when IME status +is changed and pre-edit text is not empty. -When the focus is gone from text box, you can use the following functions to reset IME status: +When the focus is gone from text box, you can use @ref glfwSetInputMode, @ref +glfwGetInputMode with the `GLFW_IME` mode and the @ref glfwResetPreeditText +function. -@code -void glfwResetPreeditText(GLFWwindow* window); -void glfwSetIMEStatus(GLFWwindow* window, int active) -int glfwGetIMEStatus(GLFWwindow* window) -@endcode @subsection input_key_name Key names diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index a402673f..2a877407 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1106,7 +1106,6 @@ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); * This is the function signature for preedit callback functions. * * @param[in] window The window that received the event. - * @param[in] length Preedit string length. * @param[in] string Preedit string. * @param[in] count Attributed block count. * @param[in] blocksizes List of attributed block size. @@ -1117,7 +1116,7 @@ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); * * @ingroup input */ -typedef void (* GLFWpreeditfun)(GLFWwindow*,int,unsigned int*,int,int*,int); +typedef void (* GLFWpreeditfun)(GLFWwindow*,unsigned int*,int,int*,int); /*! @brief The function signature for IME status change callbacks. * diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 95516f94..cc042f81 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -721,33 +721,17 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; NSString* markedTextString = markedText.string; NSUInteger i, length = [markedTextString length]; - int ctext = window->ctext; - while (ctext < length + 1) - ctext = ctext ? ctext * 2 : 1; - if (ctext != window->ctext) - { - unsigned int* preeditText = realloc(window->preeditText, sizeof(unsigned int) * ctext); - if (!preeditText) - return; - - window->preeditText = preeditText; - window->ctext = ctext; - } - - window->ntext = length; - window->preeditText[length] = 0; + free(window->preeditText); + window->preeditText = calloc(length + 1, sizeof(unsigned int)); for (i = 0; i < length; i++) - { - const unichar codepoint = [markedTextString characterAtIndex:i]; - window->preeditText[i] = codepoint; - } + window->preeditText[i] = [markedTextString characterAtIndex:i]; int focusedBlock = 0; NSInteger offset = 0; - window->nblocks = 0; + window->preeditBlockCount = 0; while (offset < length) { @@ -755,27 +739,18 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; NSDictionary *attributes = [markedText attributesAtIndex:offset effectiveRange:&effectiveRange]; - if (window->nblocks == window->cblocks) - { - int cblocks = window->cblocks * 2; - int* blocks = realloc(window->preeditAttributeBlocks, sizeof(int) * cblocks); - if (!blocks) - return; + window->preeditBlockCount++; + window->preeditBlocks = realloc(window->preeditBlocks, + window->preeditBlockCount * sizeof(int)); - window->preeditAttributeBlocks = blocks; - window->cblocks = cblocks; - } - - window->preeditAttributeBlocks[window->nblocks] = effectiveRange.length; + window->preeditBlocks[window->preeditBlockCount - 1] = effectiveRange.length; offset += effectiveRange.length; if (!effectiveRange.length) break; NSNumber* underline = (NSNumber*) [attributes objectForKey:@"NSUnderline"]; if ([underline intValue] != 1) - focusedBlock = window->nblocks; - - window->nblocks++; + focusedBlock = window->preeditBlockCount - 1; } _glfwInputPreedit(window, focusedBlock); diff --git a/src/input.c b/src/input.c index 1574dda3..c802b946 100644 --- a/src/input.c +++ b/src/input.c @@ -84,10 +84,9 @@ void _glfwInputPreedit(_GLFWwindow* window, int focusedBlock) if (window->callbacks.preedit) { window->callbacks.preedit((GLFWwindow*) window, - window->ntext, window->preeditText, - window->nblocks, - window->preeditAttributeBlocks, + window->preeditBlockCount, + window->preeditBlocks, focusedBlock); } } diff --git a/src/internal.h b/src/internal.h index 53c8fa0f..193e8639 100644 --- a/src/internal.h +++ b/src/internal.h @@ -374,13 +374,10 @@ struct _GLFWwindow // Virtual cursor position when cursor is disabled double virtualCursorPosX, virtualCursorPosY; - // Preedit texts + // IME preedit data unsigned int* preeditText; - int ntext; - int ctext; - int* preeditAttributeBlocks; - int nblocks; - int cblocks; + int* preeditBlocks; + int preeditBlockCount; int preeditCaretPosX, preeditCaretPosY; int preeditCaretHeight; diff --git a/src/win32_window.c b/src/win32_window.c index d2c97845..5c80b836 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -425,12 +425,12 @@ static void releaseMonitor(_GLFWwindow* window) // Set cursor position to decide candidate window // -static void changeCaretPosition(HIMC imc, _GLFWwindow* window) +static void updateCaretPosition(_GLFWwindow* window, HIMC imc) { const int x = window->preeditCaretPosX; const int y = window->preeditCaretPosY; const int h = window->preeditCaretHeight; - CANDIDATEFORM excludeRect = {0, CFS_EXCLUDE, {x, y}, {x, y, x, y + h}}; + CANDIDATEFORM excludeRect = { 0, CFS_EXCLUDE, { x, y }, { x, y, x, y + h } }; ImmSetCandidateWindow(imc, &excludeRect); } @@ -586,12 +586,15 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_IME_COMPOSITION: { HIMC imc; - LONG preeditTextLength, attrLength, clauseLength; + LONG textSize, attrSize, clauseSize; + int i, focusedBlock, length; + LPWSTR buffer; + LPSTR attributes; + DWORD* clauses; if (lParam & GCS_RESULTSTR) { - window->nblocks = 0; - window->ntext = 0; + window->preeditBlockCount = 0; _glfwInputPreedit(window, 0); return TRUE; } @@ -600,88 +603,49 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, break; imc = ImmGetContext(hWnd); - preeditTextLength = ImmGetCompositionStringW(imc, GCS_COMPSTR, NULL, 0); - attrLength = ImmGetCompositionString(imc, GCS_COMPATTR, NULL, 0); - clauseLength = ImmGetCompositionString(imc, GCS_COMPCLAUSE, NULL, 0); + textSize = ImmGetCompositionStringW(imc, GCS_COMPSTR, NULL, 0); + attrSize = ImmGetCompositionStringW(imc, GCS_COMPATTR, NULL, 0); + clauseSize = ImmGetCompositionStringW(imc, GCS_COMPCLAUSE, NULL, 0); - if (preeditTextLength > 0) + if (textSize <= 0) { - // get preedit data - int i, ctext, cblocks, focusedBlock, length = preeditTextLength / sizeof(WCHAR); - LPWSTR buffer = malloc(sizeof(WCHAR) + preeditTextLength); - LPSTR attributes = malloc(attrLength); - DWORD* clauses = malloc(clauseLength); - - ImmGetCompositionStringW(imc, GCS_COMPSTR, buffer, preeditTextLength); - ImmGetCompositionString(imc, GCS_COMPATTR, attributes, attrLength); - ImmGetCompositionString(imc, GCS_COMPCLAUSE, clauses, clauseLength); - - // store preedit text - ctext = window->ctext; - while (ctext < length + 1) - ctext = ctext ? ctext * 2 : 1; - - if (ctext != window->ctext) - { - unsigned int* preeditText = realloc(window->preeditText, sizeof(unsigned int) * ctext); - if (!preeditText) - { - free(buffer); - free(attributes); - free(clauses); - return FALSE; - } - - window->preeditText = preeditText; - window->ctext = ctext; - } - - window->ntext = length; - window->preeditText[length] = 0; - for (i = 0; i < length; i++) - window->preeditText[i] = buffer[i]; - - // store blocks - window->nblocks = clauseLength / sizeof(DWORD) - 1; - - // last element of clauses is a block count, but - // text length is convenient. - clauses[window->nblocks] = length; - cblocks = window->cblocks; - while (cblocks < window->nblocks) - cblocks = (cblocks == 0) ? 1 : cblocks * 2; - - if (cblocks != window->cblocks) - { - int* blocks = realloc(window->preeditAttributeBlocks, sizeof(int) * cblocks); - if (!blocks) - { - free(buffer); - free(attributes); - free(clauses); - return FALSE; - } - - window->preeditAttributeBlocks = blocks; - window->cblocks = cblocks; - } - - focusedBlock = 0; - for (i = 0; i < window->nblocks; i++) - { - window->preeditAttributeBlocks[i] = clauses[i + 1] - clauses[i]; - if (attributes[clauses[i]] != ATTR_CONVERTED) - focusedBlock = i; - } - - free(buffer); - free(attributes); - free(clauses); - - _glfwInputPreedit(window, focusedBlock); - changeCaretPosition(imc, window); + ImmReleaseContext(hWnd, imc); + return TRUE; } + length = textSize / sizeof(WCHAR); + buffer = calloc(length + 1, sizeof(WCHAR)); + attributes = calloc(attrSize, 1); + clauses = calloc(clauseSize, 1); + + ImmGetCompositionStringW(imc, GCS_COMPSTR, buffer, textSize); + ImmGetCompositionStringW(imc, GCS_COMPATTR, attributes, attrSize); + ImmGetCompositionStringW(imc, GCS_COMPCLAUSE, clauses, clauseSize); + + free(window->preeditText); + window->preeditText = calloc(length + 1, sizeof(unsigned int)); + memcpy(window->preeditText, buffer, sizeof(unsigned int) * length); + + focusedBlock = 0; + + window->preeditBlockCount = clauseSize / sizeof(DWORD) - 1; + free(window->preeditBlocks); + window->preeditBlocks = calloc(window->preeditBlockCount, sizeof(int)); + + for (i = 0; i < window->preeditBlockCount; i++) + { + window->preeditBlocks[i] = clauses[i + 1] - clauses[i]; + if (attributes[clauses[i]] != ATTR_CONVERTED) + focusedBlock = i; + } + + free(buffer); + free(attributes); + free(clauses); + + _glfwInputPreedit(window, focusedBlock); + updateCaretPosition(window, imc); + ImmReleaseContext(hWnd, imc); return TRUE; } diff --git a/src/window.c b/src/window.c index c6ce32b1..b7e4c49a 100644 --- a/src/window.c +++ b/src/window.c @@ -404,7 +404,7 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle) _glfwPlatformDestroyWindow(window); free(window->preeditText); - free(window->preeditAttributeBlocks); + free(window->preeditBlocks); // Unlink window from global linked list { diff --git a/src/x11_window.c b/src/x11_window.c index 0fcc3aa8..1a774c6d 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -440,194 +440,216 @@ static char** parseUriList(char* text, int* count) return paths; } -// Update cursor position to decide candidate window -static void _ximChangeCursorPosition(XIC xic, _GLFWwindow* window) +// Update caret position to decide candidate window +// +static void updateCaretPosition(_GLFWwindow* window, XIC xic) { - XVaNestedList preedit_attr; - XPoint spot; + XVaNestedList attributes; + 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); + attributes = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL); + XSetICValues(xic, XNPreeditAttributes, attributes, NULL); + XFree(attributes); } -// IME Start callback (do nothing) -static void _ximPreeditStartCallback(XIC xic, XPointer clientData, XPointer callData) +// IME start callback (do nothing) +// +static void preeditStartCallback(XIC xic, XPointer clientData, XPointer callData) { } -// IME Done callback (do nothing) -static void _ximPreeditDoneCallback(XIC xic, XPointer clientData, XPointer callData) +// IME done callback (do nothing) +// +static void preeditDoneCallback(XIC xic, XPointer clientData, XPointer callData) { } -// IME Draw callback -static void _ximPreeditDrawCallback(XIC xic, XPointer clientData, XIMPreeditDrawCallbackStruct *callData) +// IME draw callback +// +static void preeditDrawCallback(XIC xic, XPointer clientData, XIMPreeditDrawCallbackStruct* callData) { - int i, j, length, ctext, rstart, rend; + int i, j, length, rstart, rend; XIMText* text; const char* src; unsigned int codePoint; unsigned int* preeditText; XIMFeedback f; - _GLFWwindow* window = (_GLFWwindow*)clientData; + _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 - window->ntext = 0; - window->nblocks = 0; + if (!callData->text) + { + // Composition string is empty + window->preeditBlockCount = 0; _glfwInputPreedit(window, 0); return; - } else { + } + else + { text = callData->text; length = callData->chg_length; - if (text->encoding_is_wchar) { + if (text->encoding_is_wchar) + { // wchar is not supported return; } - ctext = window->ctext; - while (ctext < length+1) { - ctext = (ctext == 0) ? 1 : ctext * 2; - } - if (ctext != window->ctext) { - preeditText = realloc(window->preeditText, sizeof(unsigned int)*ctext); - if (preeditText == NULL) { - return; - } - window->preeditText = preeditText; - window->ctext = ctext; - } - window->ntext = length; - window->preeditText[length] = 0; - if (window->cblocks == 0) { - window->preeditAttributeBlocks = malloc(sizeof(int)*4); - window->cblocks = 4; - } + + free(window->preeditText); + window->preeditText = calloc(length + 1, sizeof(unsigned int)); + + if (!window->preeditBlocks) + window->preeditBlocks = calloc(4, sizeof(int)); + src = text->string.multi_byte; rend = 0; rstart = length; - for (i = 0, j = 0; i < text->length; i++) { - #if defined(X_HAVE_UTF8_STRING) + + for (i = 0, j = 0; i < text->length; i++) + { +#if defined(X_HAVE_UTF8_STRING) codePoint = decodeUTF8(&src); - #else +#else codePoint = *src; src++; - #endif - if (i < callData->chg_first || callData->chg_first+length < i) { +#endif + if (i < callData->chg_first || callData->chg_first + length < i) continue; - } + window->preeditText[j++] = codePoint; f = text->feedback[i]; - if ((f & XIMReverse) || (f & XIMHighlight)) { + + if ((f & XIMReverse) || (f & XIMHighlight)) + { rend = i; - if (i < rstart) { + if (i < rstart) rstart = i; - } } } - if (rstart == length) { - window->nblocks = 1; - window->preeditAttributeBlocks[0] = length; - window->preeditAttributeBlocks[1] = 0; + + if (rstart == length) + { + window->preeditBlockCount = 1; + window->preeditBlocks[0] = length; + window->preeditBlocks[1] = 0; _glfwInputPreedit(window, 0); - } else if (rstart == 0) { - if (rend == length -1) { - window->nblocks = 1; - window->preeditAttributeBlocks[0] = length; - window->preeditAttributeBlocks[1] = 0; - _glfwInputPreedit(window, 0); - } else { - window->nblocks = 2; - window->preeditAttributeBlocks[0] = rend + 1; - window->preeditAttributeBlocks[1] = length - rend - 1; - window->preeditAttributeBlocks[2] = 0; + } + else if (rstart == 0) + { + if (rend == length -1) + { + window->preeditBlockCount = 1; + window->preeditBlocks[0] = length; + window->preeditBlocks[1] = 0; _glfwInputPreedit(window, 0); } - } else if (rend == length -1) { - window->nblocks = 2; - window->preeditAttributeBlocks[0] = rstart; - window->preeditAttributeBlocks[1] = length - rstart; - window->preeditAttributeBlocks[2] = 0; - _glfwInputPreedit(window, 1); - } else { - window->nblocks = 3; - window->preeditAttributeBlocks[0] = rstart; - window->preeditAttributeBlocks[1] = rend - rstart + 1; - window->preeditAttributeBlocks[2] = length - rend - 1; - window->preeditAttributeBlocks[3] = 0; + else + { + window->preeditBlockCount = 2; + window->preeditBlocks[0] = rend + 1; + window->preeditBlocks[1] = length - rend - 1; + window->preeditBlocks[2] = 0; + _glfwInputPreedit(window, 0); + } + } + else if (rend == length -1) + { + window->preeditBlockCount = 2; + window->preeditBlocks[0] = rstart; + window->preeditBlocks[1] = length - rstart; + window->preeditBlocks[2] = 0; _glfwInputPreedit(window, 1); } - if ((cursorX != window->preeditCursorPosX) - || (cursorY != window->preeditCursorPosY) - || (cursorHeight != window->preeditCursorHeight)) { - _ximChangeCursorPosition(xic, window); + else + { + window->preeditBlockCount = 3; + window->preeditBlocks[0] = rstart; + window->preeditBlocks[1] = rend - rstart + 1; + window->preeditBlocks[2] = length - rend - 1; + window->preeditBlocks[3] = 0; + _glfwInputPreedit(window, 1); + } + + if ((caretX != window->preeditCaretPosX) || + (caretY != window->preeditCaretPosY) || + (caretHeight != window->preeditCaretHeight)) + { + updateCaretPosition(window, xic); } } } // IME Caret callback (do nothing) -static void _ximPreeditCaretCallback(XIC xic, XPointer clientData, XPointer callData) +// +static void preeditCaretCallback(XIC xic, XPointer clientData, XPointer callData) { } -static void _ximStatusStartCallback(XIC xic, XPointer clientData, XPointer callData) +static void statusStartCallback(XIC xic, XPointer clientData, XPointer callData) { - _GLFWwindow* window = (_GLFWwindow*)clientData; + _GLFWwindow* window = (_GLFWwindow*) clientData; window->x11.imeFocus = GLFW_TRUE; } -static void _ximStatusDoneCallback(XIC xic, XPointer clientData, XPointer callData) +static void statusDoneCallback(XIC xic, XPointer clientData, XPointer callData) { - _GLFWwindow* window = (_GLFWwindow*)clientData; + _GLFWwindow* window = (_GLFWwindow*) clientData; window->x11.imeFocus = GLFW_FALSE; } -static void _ximStatusDrawCallback(XIC xic, XPointer clientData, XIMStatusDrawCallbackStruct* callData) +static void statusDrawCallback(XIC xic, XPointer clientData, XIMStatusDrawCallbackStruct* callData) { - _GLFWwindow* window = (_GLFWwindow*)clientData; + _GLFWwindow* window = (_GLFWwindow*) clientData; _glfwInputIMEStatus(window); } // Create XIM Preedit callback +// static XVaNestedList _createXIMPreeditCallbacks(_GLFWwindow* window) { window->x11.preeditStartCallback.client_data = (XPointer)window; - window->x11.preeditStartCallback.callback = (XIMProc)_ximPreeditStartCallback; + window->x11.preeditStartCallback.callback = (XIMProc) preeditStartCallback; window->x11.preeditDoneCallback.client_data = (XPointer)window; - window->x11.preeditDoneCallback.callback = (XIMProc)_ximPreeditDoneCallback; + window->x11.preeditDoneCallback.callback = (XIMProc) preeditDoneCallback; window->x11.preeditDrawCallback.client_data = (XPointer)window; - window->x11.preeditDrawCallback.callback = (XIMProc)_ximPreeditDrawCallback; + window->x11.preeditDrawCallback.callback = (XIMProc) preeditDrawCallback; window->x11.preeditCaretCallback.client_data = (XPointer)window; - window->x11.preeditCaretCallback.callback = (XIMProc)_ximPreeditCaretCallback; - return XVaCreateNestedList (0, - XNPreeditStartCallback, &window->x11.preeditStartCallback.client_data, - XNPreeditDoneCallback, &window->x11.preeditDoneCallback.client_data, - XNPreeditDrawCallback, &window->x11.preeditDrawCallback.client_data, - XNPreeditCaretCallback, &window->x11.preeditCaretCallback.client_data, - NULL); + window->x11.preeditCaretCallback.callback = (XIMProc) preeditCaretCallback; + return XVaCreateNestedList(0, + XNPreeditStartCallback, + &window->x11.preeditStartCallback.client_data, + XNPreeditDoneCallback, + &window->x11.preeditDoneCallback.client_data, + XNPreeditDrawCallback, + &window->x11.preeditDrawCallback.client_data, + XNPreeditCaretCallback, + &window->x11.preeditCaretCallback.client_data, + NULL); } // Create XIM status callback +// static XVaNestedList _createXIMStatusCallbacks(_GLFWwindow* window) { window->x11.statusStartCallback.client_data = (XPointer)window; - window->x11.statusStartCallback.callback = (XIMProc)_ximStatusStartCallback; + window->x11.statusStartCallback.callback = (XIMProc) statusStartCallback; window->x11.statusDoneCallback.client_data = (XPointer)window; - window->x11.statusDoneCallback.callback = (XIMProc)_ximStatusDoneCallback; + window->x11.statusDoneCallback.callback = (XIMProc) statusDoneCallback; window->x11.statusDrawCallback.client_data = (XPointer)window; - window->x11.statusDrawCallback.callback = (XIMProc)_ximStatusDrawCallback; - return XVaCreateNestedList (0, - XNStatusStartCallback, &window->x11.statusStartCallback.client_data, - XNStatusDoneCallback, &window->x11.statusDoneCallback.client_data, - XNStatusDrawCallback, &window->x11.statusDrawCallback.client_data, - NULL); + window->x11.statusDrawCallback.callback = (XIMProc) statusDrawCallback; + return XVaCreateNestedList(0, + XNStatusStartCallback, + &window->x11.statusStartCallback.client_data, + XNStatusDoneCallback, + &window->x11.statusDoneCallback.client_data, + XNStatusDrawCallback, + &window->x11.statusDrawCallback.client_data, + NULL); } // Centers the cursor over the window client area @@ -2682,47 +2704,46 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, } } -void _glfwPlatformResetPreeditText(_GLFWwindow* window) { - XIC ic = window->x11.ic; - - /* restore conversion state after resetting ic later */ - XIMPreeditState preedit_state = XIMPreeditUnKnown; - XVaNestedList preedit_attr; +void _glfwPlatformResetPreeditText(_GLFWwindow* window) +{ + // Restore conversion state after resetting ic later + XIMPreeditState state = XIMPreeditUnKnown; + XVaNestedList attributes; char* result; - if (window->ntext == 0) + if (*window->preeditText == 0) return; - preedit_attr = XVaCreateNestedList(0, XNPreeditState, &preedit_state, NULL); - XGetICValues(ic, XNPreeditAttributes, preedit_attr, NULL); - XFree(preedit_attr); + attributes = XVaCreateNestedList(0, XNPreeditState, &state, NULL); + XGetICValues(window->x11.ic, XNPreeditAttributes, attributes, NULL); + XFree(attributes); - result = XmbResetIC(ic); + result = XmbResetIC(window->x11.ic); - preedit_attr = XVaCreateNestedList(0, XNPreeditState, preedit_state, NULL); - XSetICValues(ic, XNPreeditAttributes, preedit_attr, NULL); - XFree(preedit_attr); + attributes = XVaCreateNestedList(0, XNPreeditState, state, NULL); + XSetICValues(window->x11.ic, XNPreeditAttributes, attributes, NULL); + XFree(attributes); - window->ntext = 0; - window->nblocks = 0; + window->preeditBlockCount = 0; _glfwInputPreedit(window, 0); - XFree (result); + XFree(result); } -void _glfwPlatformSetIMEStatus(_GLFWwindow* window, int active) { - XIC ic = window->x11.ic; - if (active) { - XSetICFocus(ic); - } else { - XUnsetICFocus(ic); - } +void _glfwPlatformSetIMEStatus(_GLFWwindow* window, int active) +{ + if (active) + XSetICFocus(window->x11.ic); + else + XUnsetICFocus(window->x11.ic); } -int _glfwPlatformGetIMEStatus(_GLFWwindow* window) { +int _glfwPlatformGetIMEStatus(_GLFWwindow* window) +{ return window->x11.imeFocus; } + ////////////////////////////////////////////////////////////////////////// ////// GLFW native API ////// ////////////////////////////////////////////////////////////////////////// diff --git a/tests/events.c b/tests/events.c index 9a9c3e2b..660cd247 100644 --- a/tests/events.c +++ b/tests/events.c @@ -421,7 +421,6 @@ static void char_mods_callback(GLFWwindow* window, unsigned int codepoint, int m } static void preedit_callback(GLFWwindow* window, - int strLength, unsigned int* string, int blockLength, int* blocks, @@ -434,9 +433,9 @@ static void preedit_callback(GLFWwindow* window, printf("%08x to %i at %0.3f: Preedit text ", counter++, slot->number, glfwGetTime()); - if (strLength && blockLength) + if (*string && blockLength) { - for (i = 0; i < strLength; i++) + for (i = 0; string[i]; i++) { if (blockCount == 0) {