ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
57.8k stars 9.91k forks source link

Button like "clicked" callback/return value in InputText #4771

Open Slluxx opened 2 years ago

Slluxx commented 2 years ago

Hello,

i'm working on the Nintendo Switch which uses both touchscreen and gamepad navigations. Interacting with a button is as straight forward as it can be: Wrap it in an if statement and both touchscreen and the gamepad A button work as click and will execute the code inside.

    if (ImGui::Button("showKbd")){
        apiKey = openKeyboard(apiKey, 501);
    }

Trying to archive the same functionality with InputTextis giving me a lot of headaches though. I cant for my life figure out a good way to execute my apiKey = openKeyboard(apiKey, 501); once the user has "just clicked" the textinput widget with either touchscreen or gamepad.

Something like

    ImGui::InputText("input text",apiKey, IM_ARRAYSIZE(apiKey));
    if (ImGui::IsItemActive() && ImGui::IsItemClicked())
    {
        apiKey = openKeyboard(apiKey, 501);
    }

Seems to work with touch inputs but is completly ignoring the gamepad A press.

openKeyboard() opens the switchs own software keyboard and returns the output.

rokups commented 2 years ago

A correct approach would be to open a keyboard whenever ImGuiIO::WantCaptureKeyboard ImGuiIO::WantTextInput is set.

Mobile/console: when set, you may display an on-screen keyboard. This is set by Dear ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active).

ocornut commented 2 years ago

You'd want two things:

Slluxx commented 2 years ago

This seems to work just fine. The only issue i have is that after the keyboard closes and the text is added zo the widget, the keyboard opens again. Imgui doesnt know when my software keyboard closes (obviously) but whats the best way to tell imgui that it shouldnt want input anymore?

ocornut commented 2 years ago

The "enter/validation" key of your keyboard should probably send a ImGuiNavInput_Input event (io.NavInputs[ImGuiNavInput_Input] = 1.0f;) The "cancel" key of your keyboard should send a ImGuiNavInput_Cancel event.

Slluxx commented 2 years ago
    ImGuiIO &io = ImGui::GetIO();
    (void)io;

    io.ConfigFlags |= ImGuiConfigFlags_NavEnableSetMousePos;
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;

    // ....

    while (!glfwWindowShouldClose(window))
    {
        if(io.WantTextInput){
            io.AddInputCharactersUTF8(openKeyboard("", 501).c_str());
            // io.NavInputs[ImGuiNavInput_Input] = 1.0f;
            io.NavInputs[ImGuiNavInput_Cancel] = 1.0f;
        }

        // .... (newframe etc)
    }

Multiple things

I have to write the code like that because the keyboard does not have any callbacks. Well, the Switch has 2 keyboards: Fullsized and Inline. Only the inline keyboard has callbacks but i dont want to use that because of a few unrelated reasons. openKeyboard always returns a string.

averne commented 2 years ago

This seems to work just fine. The only issue i have is that after the keyboard closes and the text is added zo the widget, the keyboard opens again. Imgui doesnt know when my software keyboard closes (obviously) but whats the best way to tell imgui that it shouldnt want input anymore?

Bit of a hack, but I worked around the same issue with this: https://github.com/averne/Fizeau/blob/master/application/src/swkbd.hpp#L34