jvcleave / ofxImGui

Use ImGui in openFrameworks
296 stars 124 forks source link

ofKeyEventArgs.codepoint not right when use IME input #20

Open Geistyp opened 8 years ago

Geistyp commented 8 years ago

according to https://github.com/ocornut/imgui/blob/master/examples/opengl3_example/imgui_impl_glfw_gl3.cpp

we should use glfwSetCharCallback(window, ImGui_ImplGlfwGL3_CharCallback) to AddInputCharacter()

since like ofKeyEventArgs.codepoint is not the right unicode char, maybe this is a oF core bug.

so I comment all AddInputCharacter in KeyPressed and KeyReleased

void BaseEngine::onKeyPressed(ofKeyEventArgs& event)
{
    int key = event.keycode;
    io->KeysDown[key] = true;
    //io->AddInputCharacter((unsigned short)event.codepoint);
}
void EngineGLFW::onKeyReleased(ofKeyEventArgs& event)
{
    int key = event.keycode;
    io->KeysDown[key] = false;

    io->KeyCtrl  = io->KeysDown[GLFW_KEY_LEFT_CONTROL] || io->KeysDown[GLFW_KEY_RIGHT_CONTROL];
    io->KeyShift = io->KeysDown[GLFW_KEY_LEFT_SHIFT]   || io->KeysDown[GLFW_KEY_RIGHT_SHIFT];
    io->KeyAlt   = io->KeysDown[GLFW_KEY_LEFT_ALT]     || io->KeysDown[GLFW_KEY_RIGHT_ALT];
    if(key < GLFW_KEY_ESCAPE)
    {
        //io->AddInputCharacter((unsigned short)event.codepoint);
    }
}

And add CharCallback then all works

void ImGui_ImplGlfwGL3_CharCallback(GLFWwindow*, unsigned int c)
{
    ImGuiIO& io = ImGui::GetIO();
    if (c > 0 && c < 0x10000)
        io.AddInputCharacter((unsigned short)c);
}
void EngineGLFW::setup(ImGuiIO* io_)
{
    ......
    ofAddListener(ofEvents().keyReleased, this, &EngineGLFW::onKeyReleased);

    ofAddListener(ofEvents().keyPressed, (BaseEngine*)this, &BaseEngine::onKeyPressed);
    ofAddListener(ofEvents().mousePressed, (BaseEngine*)this, &BaseEngine::onMousePressed);
    ofAddListener(ofEvents().mouseReleased, (BaseEngine*)this, &BaseEngine::onMouseReleased);
    ofAddListener(ofEvents().mouseScrolled, (BaseEngine*)this, &BaseEngine::onMouseScrolled);
    ofAddListener(ofEvents().windowResized, (BaseEngine*)this, &BaseEngine::onWindowResized);

    auto ptr = static_cast<ofAppGLFWWindow*>(ofGetWindowPtr());
    glfwSetCharCallback(ptr->getGLFWWindow(), ImGui_ImplGlfwGL3_CharCallback);
}

oF not use this CallBack in glfw setting, so it's fine we use here.

jvcleave commented 8 years ago

I think there may be some Unicode/UTF-8 in OF 0.9.0

Take a look at this and see if it may help http://blog.openframeworks.cc/post/133404738514/openframeworks-090-ofthreadchannel-utf-8-and

Especially the section about ofAppendUTF8(str,key)

Geistyp commented 8 years ago

Yes, but ImGui combine key code to string and parse to utf8, we just use AddInputCharacter to add key code.

https://github.com/arturoc/glfw/blob/feature-keysUnicode/src/win32_window.c#L320

        case WM_SYSKEYDOWN:
        {
            const int scancode = (lParam >> 16) & 0x1ff;
            const int key = translateKey(wParam, lParam);
            if (key == _GLFW_KEY_INVALID)
                                break;
                        const int unicode = translateToUnicode(wParam,scancode);

                        _glfwInputKey(window, key, scancode, unicode, GLFW_PRESS, getKeyMods());
            break;
        }

        case WM_CHAR:
        {
            _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GL_TRUE);
            return 0;
        }

        case WM_SYSCHAR:
        {
            _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GL_FALSE);
            return 0;
        }

        case WM_UNICHAR:
        {
            // This message is not sent by Windows, but is sent by some
            // third-party input method engines

            if (wParam == UNICODE_NOCHAR)
            {
                // Returning TRUE here announces support for this message
                return TRUE;
            }

            _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GL_TRUE);
            return FALSE;
        }

oF already translate char to unicode, but ImGui input just need (unsigned int) wParam

There is no different change to use glfwSetCharCallback(), but add features to support IME input.

jvcleave commented 8 years ago

ok - I think I understand. I will take a look

o2co2 commented 8 years ago

@Geistyp

static char buf[256] = "";
        bool isinput = ImGui::InputText(ofLocaleToUtf8("输入中文").c_str(), buf, IM_ARRAYSIZE(buf));
        if (isinput)
        {
            ofLogNotice(  ofToString(buf) );
        }

display Garbled

o2co2 commented 8 years ago

@Geistyp How to convert static char buf[256]

Geistyp commented 8 years ago

@o2co2 what do you mean? Is that "输入中文" garbled? or your IME input garbled?

o2co2 commented 8 years ago

@Geistyp see the picture file-list

Geistyp commented 8 years ago

@o2co2 console output chinese? try _setlocale(LCALL, "chs");

o2co2 commented 8 years ago

@Geistyp Thank you

static char buf[256] = "";
bool isinput = ImGui::InputText(ofLocaleToUtf8("输入中文").c_str(), buf, IM_ARRAYSIZE(buf));
if (isinput)
{
      std::wstring sw = UTF8ToUnicode(ofToString(buf));
      std::string uToa = UnicodeToANSI(sw);
      ofLogNotice(uToa.c_str());
}