Add caret position to preedit-callback

- Win32: This works fine.
- macOS: The caret is always at the last of the preedit text.
- X11:
  - over-the-spot: The callback is not used.
  - on-the-spot: In IBus, the caret is always at the last of the preedit
    text, although the actual position can be changed. On-the-spot on X11
    has many other unstable behaviors, so allow this problem for now.
This commit is contained in:
Daijiro Fukuda 2022-05-30 14:41:10 +09:00
parent 7563d1bce0
commit 0ba4b36557
9 changed files with 51 additions and 20 deletions

View File

@ -255,7 +255,8 @@ void preedit_callback(GLFWwindow* window,
unsigned int* preedit_string,
int block_count,
int* block_sizes,
int focused_block)
int focused_block,
int caret)
{
}
@endcode
@ -273,7 +274,7 @@ times like the following sequence:
-# key event: s
-# preedit: [preedit_string: "すs", block_sizes: [2], focused_block: 0]
-# key event: h
-# preedit: [preedit_string: "すsh", block_sizes: [2], focused_block: 0]
-# preedit: [preedit_string: "すsh", block_sizes: [3], focused_block: 0]
-# key event: i
-# preedit: [preedit_string: "すし", block_sizes: [2], focused_block: 0]
-# key event: ' '
@ -296,6 +297,16 @@ blocks and the second block is focused.
The application side should draw a focused block and unfocused blocks
in different styles.
You can use the "caret" parameter to draw the caret of the preedit text.
The specification of this parameter depends on the specification of the input method.
The following is an example on Win32.
- "あいうえお|" (caret: 5)
- key event: arrow-left
- "あいうえ|お" (caret: 4)
- ...
- "|あいうえお" (caret: 0)
GLFW provides helper functions to teach the suitable position of the candidate window
to the window system. The window system decides the best position from text cursor
geometry (x, y coords and height).

View File

@ -1893,6 +1893,7 @@ typedef void (* GLFWcharmodsfun)(GLFWwindow* window, unsigned int codepoint, int
* @param[in] block_count Attributed block count.
* @param[in] block_sizes List of attributed block size.
* @param[in] focused_block Focused block index.
* @param[in] caret Caret position.
*
* @sa @ref preedit
* @sa glfwSetPreeditCallback
@ -1904,7 +1905,8 @@ typedef void (* GLFWpreeditfun)(GLFWwindow* window,
unsigned int* preedit_string,
int block_count,
int* block_sizes,
int focused_block);
int focused_block,
int caret);
/*! @brief The function pointer type for IME status change callbacks.
*
@ -5277,7 +5279,8 @@ GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmods
unsigned int* preedit_string,
int block_count,
int* block_sizes,
int focused_block)
int focused_block,
int caret)
* @endcode
* For more information about the callback parameters, see the
* [function pointer type](@ref GLFWpreeditfun).

View File

@ -763,7 +763,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
focusedBlock = window->nblocks;
window->nblocks++;
}
_glfwInputPreedit(window, focusedBlock);
// The caret is always at the last of preedit in macOS.
_glfwInputPreedit(window, focusedBlock, window->ntext);
}
- (void)unmarkText
@ -771,7 +772,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
[[markedText mutableString] setString:@""];
window->nblocks = 0;
window->ntext = 0;
_glfwInputPreedit(window, 0);
_glfwInputPreedit(window, 0, 0);
}
- (NSArray*)validAttributesForMarkedText

View File

@ -315,7 +315,7 @@ void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool
// Notifies shrared code of a preedit event
//
void _glfwInputPreedit(_GLFWwindow* window, int focusedBlock)
void _glfwInputPreedit(_GLFWwindow* window, int focusedBlock, int caret)
{
if (window->callbacks.preedit)
{
@ -324,7 +324,8 @@ void _glfwInputPreedit(_GLFWwindow* window, int focusedBlock)
window->preeditText,
window->nblocks,
window->preeditAttributeBlocks,
focusedBlock);
focusedBlock,
caret);
}
}

View File

@ -936,7 +936,7 @@ void _glfwInputKey(_GLFWwindow* window,
int key, int scancode, int action, int mods);
void _glfwInputChar(_GLFWwindow* window,
uint32_t codepoint, int mods, GLFWbool plain);
void _glfwInputPreedit(_GLFWwindow* window, int focusedBlock);
void _glfwInputPreedit(_GLFWwindow* window, int focusedBlock, int caret);
void _glfwInputIMEStatus(_GLFWwindow* window);
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset);
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);

View File

@ -577,6 +577,7 @@ static GLFWbool getImmPreedit(_GLFWwindow* window)
LONG preeditBytes = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0);
LONG attrBytes = ImmGetCompositionStringW(hIMC, GCS_COMPATTR, NULL, 0);
LONG clauseBytes = ImmGetCompositionStringW(hIMC, GCS_COMPCLAUSE, NULL, 0);
LONG cursorPos = ImmGetCompositionStringW(hIMC, GCS_CURSORPOS, NULL, 0);
if (preeditBytes > 0)
{
@ -663,7 +664,7 @@ static GLFWbool getImmPreedit(_GLFWwindow* window)
_glfw_free(attributes);
_glfw_free(clauses);
_glfwInputPreedit(window, focusedBlock);
_glfwInputPreedit(window, focusedBlock, cursorPos);
}
ImmReleaseContext(window->win32.handle, hIMC);
@ -994,7 +995,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
{
window->nblocks = 0;
window->ntext = 0;
_glfwInputPreedit(window, 0);
_glfwInputPreedit(window, 0, 0);
commitImmResultStr(window);
return TRUE;
}

View File

@ -574,7 +574,7 @@ static void _ximPreeditDrawCallback(XIC xic, XPointer clientData, XIMPreeditDraw
// preedit text is empty
window->ntext = 0;
window->nblocks = 0;
_glfwInputPreedit(window, 0);
_glfwInputPreedit(window, 0, 0);
return;
}
else
@ -634,7 +634,7 @@ static void _ximPreeditDrawCallback(XIC xic, XPointer clientData, XIMPreeditDraw
window->nblocks = 1;
window->preeditAttributeBlocks[0] = length;
window->preeditAttributeBlocks[1] = 0;
_glfwInputPreedit(window, 0);
_glfwInputPreedit(window, 0, callData->caret);
}
else if (rstart == 0)
{
@ -643,7 +643,7 @@ static void _ximPreeditDrawCallback(XIC xic, XPointer clientData, XIMPreeditDraw
window->nblocks = 1;
window->preeditAttributeBlocks[0] = length;
window->preeditAttributeBlocks[1] = 0;
_glfwInputPreedit(window, 0);
_glfwInputPreedit(window, 0, callData->caret);
}
else
{
@ -651,7 +651,7 @@ static void _ximPreeditDrawCallback(XIC xic, XPointer clientData, XIMPreeditDraw
window->preeditAttributeBlocks[0] = rend + 1;
window->preeditAttributeBlocks[1] = length - rend - 1;
window->preeditAttributeBlocks[2] = 0;
_glfwInputPreedit(window, 0);
_glfwInputPreedit(window, 0, callData->caret);
}
}
else if (rend == length - 1)
@ -660,7 +660,7 @@ static void _ximPreeditDrawCallback(XIC xic, XPointer clientData, XIMPreeditDraw
window->preeditAttributeBlocks[0] = rstart;
window->preeditAttributeBlocks[1] = length - rstart;
window->preeditAttributeBlocks[2] = 0;
_glfwInputPreedit(window, 1);
_glfwInputPreedit(window, 1, callData->caret);
}
else
{
@ -669,7 +669,7 @@ static void _ximPreeditDrawCallback(XIC xic, XPointer clientData, XIMPreeditDraw
window->preeditAttributeBlocks[1] = rend - rstart + 1;
window->preeditAttributeBlocks[2] = length - rend - 1;
window->preeditAttributeBlocks[3] = 0;
_glfwInputPreedit(window, 1);
_glfwInputPreedit(window, 1, callData->caret);
}
}
}
@ -3298,7 +3298,7 @@ void _glfwResetPreeditTextX11(_GLFWwindow* window)
window->ntext = 0;
window->nblocks = 0;
_glfwInputPreedit(window, 0);
_glfwInputPreedit(window, 0, 0);
XFree (result);
}

View File

@ -456,7 +456,7 @@ static void char_callback(GLFWwindow* window, unsigned int codepoint)
static void preedit_callback(GLFWwindow* window, int strLength,
unsigned int* string, int blockLength,
int* blocks, int focusedBlock)
int* blocks, int focusedBlock, int caret)
{
Slot* slot = glfwGetWindowUserPointer(window);
int i, blockIndex = -1, blockCount = 0;
@ -482,12 +482,16 @@ static void preedit_callback(GLFWwindow* window, int strLength,
if (blockIndex == focusedBlock)
printf("[");
}
if (i == caret)
printf("|");
encode_utf8(encoded, string[i]);
printf("%s", encoded);
blockCount--;
}
if (blockIndex == focusedBlock)
printf("]");
if (caret == strLength)
printf("|");
printf("\n");
glfwGetWindowSize(window, &width, &height);
glfwSetPreeditCursorPos(window, width/2, height/2, 20);

View File

@ -516,7 +516,7 @@ static void ime_callback(GLFWwindow* window)
static void preedit_callback(GLFWwindow* window, int strLength,
unsigned int* string, int blockLength,
int* blocks, int focusedBlock)
int* blocks, int focusedBlock, int caret)
{
int blockIndex = -1, blockCount = 0;
if (strLength == 0 || blockLength == 0)
@ -531,6 +531,11 @@ static void preedit_callback(GLFWwindow* window, int strLength,
{
char encoded[5] = "";
if (i == caret)
{
if (strlen(preeditBuf) + strlen("|") < MAX_PREDIT_LEN)
strcat(preeditBuf, "|");
}
if (blockCount == 0)
{
if (blockIndex == focusedBlock)
@ -556,6 +561,11 @@ static void preedit_callback(GLFWwindow* window, int strLength,
if (strlen(preeditBuf) + strlen("]") < MAX_PREDIT_LEN)
strcat(preeditBuf, "]");
}
if (caret == strLength)
{
if (strlen(preeditBuf) + strlen("|") < MAX_PREDIT_LEN)
strcat(preeditBuf, "|");
}
}
int main(int argc, char** argv)