Can I use SDL_DISABLE_WINDOWS_IME, and ignore other input at the same time without hacks?

I wrote this whole nerdy essay about my problem here, but I solved my own problem on my own, but I still want to share it (because I think it is broken).
I hope this acts like a spoiler.

Summary

I love the result that SDL_DISABLE_WINDOWS_IME has because I think the floating box is usable, and it has a minimal code footprint. Also SDL’s IME text is buggy and I have problems like: https://bugzilla.libsdl.org/show_bug.cgi?id=3421.

But the problem with SDL_DISABLE_WINDOWS_IME is that when I press keys like up, down, left, right, and enter I cannot ignore those events, so I would press enter and then the IME text will be at the next line. Also an unusual effect is that textinput inputs each unicode character in multiple events. And when I look at the code, SDL_StartTextInput and SDL_StopTextInput are not respected anymore, and all input flows through the SDLK types.

My code is mainly based off the testime.c example.

I am planning on using imgui which is why I am going to use SDL_DISABLE_WINDOWS_IME anyways. I tested the example code for SDL and it seems like it also has the same problem that I have. Since I probably cannot modify the way how imgui is rendering text, I think it would be easier to just modify SDL to just allow this simple form of IME to work.

But I have heard that glfw used to have a similar problem as SDL is having, and glfw is planning on fixing this problem in version 3.4 (which has 0 closed jobs…)
https://github.com/glfw/glfw/issues/41#issuecomment-160421273

I don’t think there should be an excuse to why the most basic IME mode on windows is not possible in SDL without frustrating bugs, this also should also be in a form of a hint, and not requiring SDL to be recompiled. It is true that rendering the IME text is the most robust method right now, even if it has no candidate list. But I would rather have something that is stable and simple than having something that is half functioning.

SDL 2.0.8 stable (& .5), windows 7, c++ mingw64.

So I fixed it in a really hacky way, I just want to know what your insights are.

I used Dear Imgui’s mmi implementation which is:

#include <imm.h>
#ifdef _MSC_VER
#pragma comment(lib, "imm32")
#endif

static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y)
{
    // Notify OS Input Method Editor of text input position
    if (HWND hwnd = (HWND)GImGui->IO.ImeWindowHandle)
        if (HIMC himc = ImmGetContext(hwnd))
        {
            COMPOSITIONFORM cf;
            cf.ptCurrentPos.x = x;
            cf.ptCurrentPos.y = y;
            cf.dwStyle = CFS_FORCE_POSITION;
            ImmSetCompositionWindow(himc, &cf);
        }
}

This code is important because if you disable SDL_DISABLE_WINDOWS_IME, setting the location of SDL_SetTextInputRect does nothing. So this would create some pretty neat and standard IME usage. (of course if you may have to modify the IME font size depending where you use it, which I have no idea how to do…).

But you see, to fix the problem of moving the cursor and not ignoring the IME return, I did not use SDL_DISABLE_WINDOWS_IME but instead wrote this hack.

It’s nasty, and I am not proud of it. I figured this out with trial and error, which is why I want to ask you why my code works, how could the code be better, and what problems could surface from this code.

Inside of src/video/windows/SDL_windowskeyboard.c
in the function SDL_bool IME_HandleMesage I modified this case to have the block comment:

case WM_IME_COMPOSITION:
        trap = SDL_TRUE;
        himc = ImmGetContext(hwnd);
        /*if (*lParam & GCS_RESULTSTR) {
            IME_GetCompositionString(videodata, himc, GCS_RESULTSTR);
            IME_SendInputEvent(videodata);
        }*/
        if (*lParam & GCS_COMPSTR) {
            if (!videodata->ime_uiless)
                videodata->ime_readingstring[0] = 0;
            IME_GetCompositionString(videodata, himc, GCS_COMPSTR);
            IME_SendEditingEvent(videodata);
        }
        ImmReleaseContext(hwnd, himc);

And at the end of the function, I just replaced the return from SDL_bool trap with just returning SDL_FALSE ALWAYS.

If I didn’t do the modification to WM_IME_COMPOSITION I would have a duplicate of the IME input text. The first input would be all the text in one bunch, the second bunch goes one by one…

The only problem I have now is the fact that the windoes IME candidate list does not render sadly, but the google IME does! And a minor issue with the location of the IME text box does not immediately snap to the area I am typing for only the first word that I enter.

2 Likes