mirror of https://github.com/libsdl-org/SDL.git
checkkeys: draw the IME composition text
This commit is contained in:
parent
018ca39c45
commit
382494eeda
105
test/checkkeys.c
105
test/checkkeys.c
|
|
@ -28,35 +28,53 @@
|
||||||
|
|
||||||
#define CURSOR_BLINK_INTERVAL_MS 500
|
#define CURSOR_BLINK_INTERVAL_MS 500
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SDLTest_TextWindow *textwindow;
|
||||||
|
char *edit_text;
|
||||||
|
int edit_cursor;
|
||||||
|
int edit_length;
|
||||||
|
} TextWindowState;
|
||||||
|
|
||||||
static SDLTest_CommonState *state;
|
static SDLTest_CommonState *state;
|
||||||
static SDLTest_TextWindow **textwindows;
|
static TextWindowState *windowstates;
|
||||||
static SDL_bool escape_pressed;
|
static SDL_bool escape_pressed;
|
||||||
static SDL_bool cursor_visible;
|
static SDL_bool cursor_visible;
|
||||||
static Uint64 last_cursor_change;
|
static Uint64 last_cursor_change;
|
||||||
static int done;
|
static int done;
|
||||||
|
|
||||||
static SDLTest_TextWindow *GetTextWindowForWindowID(SDL_WindowID id)
|
static TextWindowState *GetTextWindowStateForWindowID(SDL_WindowID id)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < state->num_windows; ++i) {
|
for (i = 0; i < state->num_windows; ++i) {
|
||||||
if (id == SDL_GetWindowID(state->windows[i])) {
|
if (id == SDL_GetWindowID(state->windows[i])) {
|
||||||
return textwindows[i];
|
return &windowstates[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SDLTest_TextWindow *GetTextWindowForWindowID(SDL_WindowID id)
|
||||||
|
{
|
||||||
|
TextWindowState *windowstate = GetTextWindowStateForWindowID(id);
|
||||||
|
if (windowstate) {
|
||||||
|
return windowstate->textwindow;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void UpdateTextWindowInputRect(SDL_WindowID id)
|
static void UpdateTextWindowInputRect(SDL_WindowID id)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < state->num_windows; ++i) {
|
for (i = 0; i < state->num_windows; ++i) {
|
||||||
if (id == SDL_GetWindowID(state->windows[i])) {
|
if (id == SDL_GetWindowID(state->windows[i])) {
|
||||||
|
SDLTest_TextWindow *textwindow = windowstates[i].textwindow;
|
||||||
int w, h;
|
int w, h;
|
||||||
SDL_Rect rect;
|
SDL_Rect rect;
|
||||||
int current = textwindows[i]->current;
|
int current = textwindow->current;
|
||||||
const char *current_line = textwindows[i]->lines[current];
|
const char *current_line = textwindow->lines[current];
|
||||||
|
|
||||||
SDL_GetWindowSize(state->windows[i], &w, &h);
|
SDL_GetWindowSize(state->windows[i], &w, &h);
|
||||||
|
|
||||||
|
|
@ -271,13 +289,18 @@ static void CountKeysDown(void)
|
||||||
static void DrawCursor(int i)
|
static void DrawCursor(int i)
|
||||||
{
|
{
|
||||||
SDL_FRect rect;
|
SDL_FRect rect;
|
||||||
int current = textwindows[i]->current;
|
TextWindowState *windowstate = &windowstates[i];
|
||||||
const char *current_line = textwindows[i]->lines[current];
|
SDLTest_TextWindow *textwindow = windowstate->textwindow;
|
||||||
|
int current = textwindow->current;
|
||||||
|
const char *current_line = textwindow->lines[current];
|
||||||
|
|
||||||
rect.x = TEXT_WINDOW_OFFSET_X;
|
rect.x = TEXT_WINDOW_OFFSET_X;
|
||||||
if (current_line) {
|
if (current_line) {
|
||||||
rect.x += SDL_utf8strlen(current_line) * FONT_CHARACTER_SIZE;
|
rect.x += SDL_utf8strlen(current_line) * FONT_CHARACTER_SIZE;
|
||||||
}
|
}
|
||||||
|
if (windowstate->edit_cursor > 0) {
|
||||||
|
rect.x += (float)windowstate->edit_cursor * FONT_CHARACTER_SIZE;
|
||||||
|
}
|
||||||
rect.y = TEXT_WINDOW_OFFSET_Y + current * FONT_LINE_HEIGHT;
|
rect.y = TEXT_WINDOW_OFFSET_Y + current * FONT_LINE_HEIGHT;
|
||||||
rect.w = FONT_CHARACTER_SIZE * 0.75f;
|
rect.w = FONT_CHARACTER_SIZE * 0.75f;
|
||||||
rect.h = (float)FONT_CHARACTER_SIZE;
|
rect.h = (float)FONT_CHARACTER_SIZE;
|
||||||
|
|
@ -286,6 +309,45 @@ static void DrawCursor(int i)
|
||||||
SDL_RenderFillRect(state->renderers[i], &rect);
|
SDL_RenderFillRect(state->renderers[i], &rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void DrawEditText(int i)
|
||||||
|
{
|
||||||
|
SDL_FRect rect;
|
||||||
|
TextWindowState *windowstate = &windowstates[i];
|
||||||
|
SDLTest_TextWindow *textwindow = windowstate->textwindow;
|
||||||
|
int current = textwindow->current;
|
||||||
|
const char *current_line = textwindow->lines[current];
|
||||||
|
|
||||||
|
if (windowstate->edit_text == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw the highlight under the selected text */
|
||||||
|
if (windowstate->edit_length > 0) {
|
||||||
|
rect.x = TEXT_WINDOW_OFFSET_X;
|
||||||
|
if (current_line) {
|
||||||
|
rect.x += SDL_utf8strlen(current_line) * FONT_CHARACTER_SIZE;
|
||||||
|
}
|
||||||
|
if (windowstate->edit_cursor > 0) {
|
||||||
|
rect.x += (float)windowstate->edit_cursor * FONT_CHARACTER_SIZE;
|
||||||
|
}
|
||||||
|
rect.y = TEXT_WINDOW_OFFSET_Y + current * FONT_LINE_HEIGHT;
|
||||||
|
rect.w = (float)windowstate->edit_length * FONT_CHARACTER_SIZE;
|
||||||
|
rect.h = (float)FONT_CHARACTER_SIZE;
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(state->renderers[i], 0xAA, 0xAA, 0xAA, 255);
|
||||||
|
SDL_RenderFillRect(state->renderers[i], &rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw the edit text */
|
||||||
|
rect.x = TEXT_WINDOW_OFFSET_X;
|
||||||
|
if (current_line) {
|
||||||
|
rect.x += SDL_utf8strlen(current_line) * FONT_CHARACTER_SIZE;
|
||||||
|
}
|
||||||
|
rect.y = TEXT_WINDOW_OFFSET_Y + current * FONT_LINE_HEIGHT;
|
||||||
|
SDL_SetRenderDrawColor(state->renderers[i], 255, 255, 0, 255);
|
||||||
|
SDLTest_DrawString(state->renderers[i], rect.x, rect.y, windowstate->edit_text);
|
||||||
|
}
|
||||||
|
|
||||||
static void loop(void)
|
static void loop(void)
|
||||||
{
|
{
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
|
|
@ -325,9 +387,22 @@ static void loop(void)
|
||||||
CountKeysDown();
|
CountKeysDown();
|
||||||
break;
|
break;
|
||||||
case SDL_EVENT_TEXT_EDITING:
|
case SDL_EVENT_TEXT_EDITING:
|
||||||
|
{
|
||||||
|
TextWindowState *windowstate = GetTextWindowStateForWindowID(event.edit.windowID);
|
||||||
|
if (windowstate->edit_text) {
|
||||||
|
SDL_free(windowstate->edit_text);
|
||||||
|
windowstate->edit_text = NULL;
|
||||||
|
}
|
||||||
|
if (event.edit.text && *event.edit.text) {
|
||||||
|
windowstate->edit_text = SDL_strdup(event.edit.text);
|
||||||
|
}
|
||||||
|
windowstate->edit_cursor = event.edit.start;
|
||||||
|
windowstate->edit_length = event.edit.length;
|
||||||
|
|
||||||
SDL_snprintf(line, sizeof(line), "EDIT %" SDL_PRIs32 ":%" SDL_PRIs32, event.edit.start, event.edit.length);
|
SDL_snprintf(line, sizeof(line), "EDIT %" SDL_PRIs32 ":%" SDL_PRIs32, event.edit.start, event.edit.length);
|
||||||
PrintText(line, event.edit.text);
|
PrintText(line, event.edit.text);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case SDL_EVENT_TEXT_INPUT:
|
case SDL_EVENT_TEXT_INPUT:
|
||||||
PrintText("INPUT", event.text.text);
|
PrintText("INPUT", event.text.text);
|
||||||
SDLTest_TextWindowAddText(GetTextWindowForWindowID(event.text.windowID), "%s", event.text.text);
|
SDLTest_TextWindowAddText(GetTextWindowForWindowID(event.text.windowID), "%s", event.text.text);
|
||||||
|
|
@ -381,7 +456,7 @@ static void loop(void)
|
||||||
SDL_SetRenderDrawColor(state->renderers[i], 255, 255, 255, 255);
|
SDL_SetRenderDrawColor(state->renderers[i], 255, 255, 255, 255);
|
||||||
SDL_snprintf(caption, sizeof(caption), "Text input %s (click right mouse button to toggle)\n", SDL_TextInputActive(state->windows[i]) ? "enabled" : "disabled");
|
SDL_snprintf(caption, sizeof(caption), "Text input %s (click right mouse button to toggle)\n", SDL_TextInputActive(state->windows[i]) ? "enabled" : "disabled");
|
||||||
SDLTest_DrawString(state->renderers[i], TEXT_WINDOW_OFFSET_X, TEXT_WINDOW_OFFSET_X, caption);
|
SDLTest_DrawString(state->renderers[i], TEXT_WINDOW_OFFSET_X, TEXT_WINDOW_OFFSET_X, caption);
|
||||||
SDLTest_TextWindowDisplay(textwindows[i], state->renderers[i]);
|
SDLTest_TextWindowDisplay(windowstates[i].textwindow, state->renderers[i]);
|
||||||
|
|
||||||
/* Draw the cursor */
|
/* Draw the cursor */
|
||||||
if ((now - last_cursor_change) >= CURSOR_BLINK_INTERVAL_MS) {
|
if ((now - last_cursor_change) >= CURSOR_BLINK_INTERVAL_MS) {
|
||||||
|
|
@ -391,6 +466,10 @@ static void loop(void)
|
||||||
if (cursor_visible) {
|
if (cursor_visible) {
|
||||||
DrawCursor(i);
|
DrawCursor(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Draw the composition text */
|
||||||
|
DrawEditText(i);
|
||||||
|
|
||||||
SDL_RenderPresent(state->renderers[i]);
|
SDL_RenderPresent(state->renderers[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -434,8 +513,8 @@ int main(int argc, char *argv[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
textwindows = (SDLTest_TextWindow **)SDL_malloc(state->num_windows * sizeof(*textwindows));
|
windowstates = (TextWindowState *)SDL_calloc(state->num_windows, sizeof(*windowstates));
|
||||||
if (!textwindows) {
|
if (!windowstates) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't allocate text windows: %s\n", SDL_GetError());
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't allocate text windows: %s\n", SDL_GetError());
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -449,7 +528,7 @@ int main(int argc, char *argv[])
|
||||||
rect.y = TEXT_WINDOW_OFFSET_Y;
|
rect.y = TEXT_WINDOW_OFFSET_Y;
|
||||||
rect.w = w - (2 * TEXT_WINDOW_OFFSET_X);
|
rect.w = w - (2 * TEXT_WINDOW_OFFSET_X);
|
||||||
rect.h = h - TEXT_WINDOW_OFFSET_Y;
|
rect.h = h - TEXT_WINDOW_OFFSET_Y;
|
||||||
textwindows[i] = SDLTest_TextWindowCreate(rect.x, rect.y, rect.w, rect.h);
|
windowstates[i].textwindow = SDLTest_TextWindowCreate(rect.x, rect.y, rect.w, rect.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SDL_PLATFORM_IOS
|
#ifdef SDL_PLATFORM_IOS
|
||||||
|
|
@ -488,9 +567,9 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
done:
|
done:
|
||||||
for (i = 0; i < state->num_windows; ++i) {
|
for (i = 0; i < state->num_windows; ++i) {
|
||||||
SDLTest_TextWindowDestroy(textwindows[i]);
|
SDLTest_TextWindowDestroy(windowstates[i].textwindow);
|
||||||
}
|
}
|
||||||
SDL_free(textwindows);
|
SDL_free(windowstates);
|
||||||
SDLTest_CleanupTextDrawing();
|
SDLTest_CleanupTextDrawing();
|
||||||
SDLTest_CommonQuit(state);
|
SDLTest_CommonQuit(state);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue