mirror of
https://github.com/glfw/glfw.git
synced 2024-11-21 20:44:35 +00:00
Cleanup
This commit is contained in:
parent
0df386d06a
commit
ed59b80cc7
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
279
src/x11_window.c
279
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 //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user