Skip to content

Commit

Permalink
Modified SDL ImGui backend, and ImGui itself, to render IME preview t…
Browse files Browse the repository at this point in the history
…ext for CJK text entry (#72645)
  • Loading branch information
katemonster33 authored Apr 9, 2024
1 parent 2c47a81 commit cb98e75
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 6 deletions.
15 changes: 13 additions & 2 deletions src/third-party/imgui/imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1261,6 +1261,17 @@ ImGuiIO::ImGuiIO()
AppAcceptingEvents = true;
BackendUsingLegacyKeyArrays = (ImS8)-1;
BackendUsingLegacyNavInputArray = true; // assume using legacy array until proven wrong
PreEditText[0] = NULL;
}

void ImGuiIO::SetPreEditText(const char *str)
{
strcpy(PreEditText, str);
}

void ImGuiIO::ClearPreEditText()
{
PreEditText[0] = NULL;
}

// Pass in translated ASCII characters for text input.
Expand Down Expand Up @@ -2467,7 +2478,7 @@ ImGuiTextFilter::ImGuiTextFilter(const char* default_filter) //-V1077

bool ImGuiTextFilter::Draw(const char* label, float width)
{
if (width != 0.0f)
if (width != 0.0f)
ImGui::SetNextItemWidth(width);
bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
if (value_changed)
Expand Down Expand Up @@ -4148,7 +4159,7 @@ ImGuiIO& ImGui::GetIO()
return GImGui->IO;
}

// Pass this to your backend rendering function! Valid after Render() and until the next call to NewFrame()
// Pass this to your backend rendering function! Valid after Render() and until the next call to NewFrame()
ImDrawData* ImGui::GetDrawData()
{
ImGuiContext& g = *GImGui;
Expand Down
3 changes: 3 additions & 0 deletions src/third-party/imgui/imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -2008,6 +2008,8 @@ struct ImGuiIO
IMGUI_API void AddInputCharacter(unsigned int c); // Queue a new character input
IMGUI_API void AddInputCharacterUTF16(ImWchar16 c); // Queue a new character input from a UTF-16 character, it can be a surrogate
IMGUI_API void AddInputCharactersUTF8(const char* str); // Queue a new characters input from a UTF-8 string
IMGUI_API void SetPreEditText(const char *str);
IMGUI_API void ClearPreEditText();

IMGUI_API void SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native_scancode, int native_legacy_index = -1); // [Optional] Specify index for legacy <1.87 IsKeyXXX() functions with native indices + specify native keycode, scancode.
IMGUI_API void SetAppAcceptingEvents(bool accepting_events); // Set master flag for accepting key/mouse/text events (default to true). Useful if you have native dialog boxes that are interrupting your application loop/refresh, and you want to disable events being queued while your app is frozen.
Expand Down Expand Up @@ -2088,6 +2090,7 @@ struct ImGuiIO
bool BackendUsingLegacyNavInputArray; // 0: using AddKeyAnalogEvent(), 1: writing to legacy io.NavInputs[] directly
ImWchar16 InputQueueSurrogate; // For AddInputCharacterUTF16()
ImVector<ImWchar> InputQueueCharacters; // Queue of _characters_ input (obtained by platform backend). Fill using AddInputCharacter() helper.
char PreEditText[255];

IMGUI_API ImGuiIO();
};
Expand Down
37 changes: 34 additions & 3 deletions src/third-party/imgui/imgui_impl_sdl2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
}
case SDL_TEXTINPUT:
{
io.ClearPreEditText();
io.AddInputCharactersUTF8(event->text.text);
return true;
}
Expand All @@ -345,6 +346,9 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
io.SetKeyEventNativeData(key, event->key.keysym.sym, event->key.keysym.scancode, event->key.keysym.scancode); // To support legacy indexing (<1.87 user code). Legacy backend uses SDLK_*** as indices to IsKeyXXX() functions.
return true;
}
case SDL_WINDOWEVENT_FOCUS_LOST:
ImGui::GetIO().ClearPreEditText();
return true;
case SDL_WINDOWEVENT:
{
// - When capturing mouse, SDL will send a bunch of conflicting LEAVE/ENTER event on every mouse move, but the final ENTER tends to be right.
Expand All @@ -358,14 +362,41 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
bd->MouseWindowID = event->window.windowID;
bd->PendingMouseLeaveFrame = 0;
}
if (window_event == SDL_WINDOWEVENT_LEAVE)
if( window_event == SDL_WINDOWEVENT_LEAVE ) {
bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1;
ImGui::GetIO().ClearPreEditText();
}
if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED)
io.AddFocusEvent(true);
else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST)
io.AddFocusEvent(false);
else if( event->window.event == SDL_WINDOWEVENT_FOCUS_LOST ) {
io.AddFocusEvent( false );
ImGui::GetIO().ClearPreEditText();
}
return true;
}
case SDL_TEXTEDITING: {
if(strlen(event->edit.text) > 0)
{
ImGui::GetIO().SetPreEditText(event->edit.text);
}
else
{
io.ClearPreEditText();
}
break;
}
#if defined(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT)
case SDL_TEXTEDITING_EXT: {
if( event->editExt.text != nullptr && strlen(event->editExt.text) > 0)
{
ImGui::GetIO().SetPreEditText( event->editExt.text );
}
else {
ImGui::GetIO().ClearPreEditText();
}
break;
}
#endif
}
return false;
}
Expand Down
28 changes: 27 additions & 1 deletion src/third-party/imgui/imgui_widgets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5012,7 +5012,33 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
{
ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);

if(GImGui->IO.PreEditText && !is_multiline)
{
const char *preEditTextEnd = GImGui->IO.PreEditText + strlen(GImGui->IO.PreEditText);
ImWchar wcharBuf[255] = { 0 };
int wlen = ImTextStrFromUtf8(wcharBuf, 255, GImGui->IO.PreEditText, preEditTextEnd);
char tmpBuf[255] = "\0";

ImVec2 drawPosStart = draw_pos - draw_scroll;
size_t tmpBufLen = ImTextStrToUtf8( tmpBuf, 255, text_begin, text_begin + state->Stb.cursor );
draw_window->DrawList->AddText(g.Font, g.FontSize, drawPosStart, col, tmpBuf, tmpBuf + tmpBufLen, 0.0f, &clip_rect);
drawPosStart.x += InputTextCalcTextSizeW(GImGui, text_begin, text_begin + state->Stb.cursor).x;
ImU32 bg_color = GetColorU32( ImGuiCol_TextSelectedBg, 1.f );
ImVec2 highlightRectMax = drawPosStart;
highlightRectMax += InputTextCalcTextSizeW(GImGui, wcharBuf, wcharBuf + wlen);
draw_window->DrawList->AddRectFilled( drawPosStart, highlightRectMax, bg_color );
draw_window->DrawList->AddText(g.Font, g.FontSize, drawPosStart, col, GImGui->IO.PreEditText, preEditTextEnd, 0.0f, &clip_rect);
if( buf_display_end != NULL && buf_display + tmpBufLen < buf_display_end )
{
drawPosStart.x = highlightRectMax.x;
draw_window->DrawList->AddText(g.Font, g.FontSize, drawPosStart, col, buf_display + tmpBufLen, buf_display_end, 0.0f, &clip_rect);
}
}
else
{
draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);
}
}

// Draw blinking cursor
Expand Down

0 comments on commit cb98e75

Please sign in to comment.