Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't enter characters with Alt-Gr modifier on Ubuntu #6034

Closed
AlexanderKaschta opened this issue Dec 31, 2022 · 8 comments
Closed

Can't enter characters with Alt-Gr modifier on Ubuntu #6034

AlexanderKaschta opened this issue Dec 31, 2022 · 8 comments

Comments

@AlexanderKaschta
Copy link

Version/Branch of Dear ImGui:

Version: 1.89.2 (18916)
Branch: docking

Back-end/Renderer/Compiler/OS

Back-ends: imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp
Compiler: g++
Operating System: Ubuntu 22.04

My Issue/Question:

When entering characters on a keyboard with German-Layout (ISO-Layout, DE-de) that require the use of the Alt-Gr-Key, those get recognized by ImGui, but don't get entered/displayed in InputText fields. Example characters are @ or }. It can be checked, that the right characters are recognized under Inputs/Chars queue in the demo window. When entering those characters, it sometimes tries to do window navigation. Rendering of those characters works perfectly in regular text fields. This issue only exists on Ubuntu, on Windows 10 (same backend with MinGW64 g++ and same code) I'm able to enter those characters.

Further testing I've done:

  • I was able to reproduce this input-issue also with version 1.89 (18810) from the docking branch under Ubuntu 22.04. Windows 10 is not affected.
  • On an even older version, v1.79 (17900), from the master branch, I wasn't able to reproduce this issue. The input of all characters works perfectly on that version for both Oses (Ubuntu & Windows).

Expected result: Enter the characters into InputText.

Screenshots/Video

small

Preview from the Inputs/Chars queue section in the demo window on Ubuntu

Standalone, minimal, complete and verifiable example:

// Include imgui_stdlib

// Define an input variable outside the render loop
std::string my_input;

// Code for the render loop
ImGui::Begin("Example Bug");
// Create an example input field
ImGui::InputText("Test", &my_input);
ImGui::End();

Try entering characters ,which require the Alt-Gr modifier, to reproduce it.

Note:

Thanks for the great work on ImGui! This is my first issue to a larger project. I hope I've provided all important information. If further information is needed, I'm happy to help.

@ocornut ocornut added the inputs label Dec 31, 2022
@ocornut
Copy link
Owner

ocornut commented Jan 2, 2023

Hello,

This issue only exists on Ubuntu, on Windows 10 (same backend with MinGW64 g++ and same code) I'm able to enter those characters.

I also cannot seem to repro this on Windows with the GLFW backend.

Does it makes a difference whether you have ImGuiConfigFlags_NavEnableKeyboard enabled or not?

don't get entered/displayed in InputText fields. Example characters are @ or }. It can be checked, that the right characters are recognized under Inputs/Chars queue in the demo window

Not your issue per-se, but one little thing to clarify: if the InputText() field is submitted before ShowDemoWindow(), you may not see the display in Inputs/Chars queue because they have already been eaten by InputText() (should rework something to make this always visible).

Other than that, I am failing to understand why the { would appear in Demo and not be seen by InputText().

What you can do to help:
After NewFrame(), add code to break when a given character is emitted, e.g.

ImGui::NewFrame();
if (io.InputQueueCharacters.Size > 0 && io.InputQueueCharacters[0] == '@')
    printf("ctrl=%d, alt=%d", io.KeyCtrl, io.Alt); // dummy statement, add breakpoint here
ImGui::InputText("...");

Then debug step into the InputText() and try to not why the character is not processed.
The code in InputText() does:

        const bool ignore_char_inputs = (io.KeyCtrl && !io.KeyAlt) || (is_osx && io.KeySuper);
....
        if (io.InputQueueCharacters.Size > 0)
        {
            if (!ignore_char_inputs && !is_readonly && !input_requested_by_nav)
                for (int n = 0; n < io.InputQueueCharacters.Size; n++)
                {
                    // Insert character if they pass filtering
                    unsigned int c = (unsigned int)io.InputQueueCharacters[n];
                    if (c == '\t') // Skip Tab, see above.
                        continue;
                    if (InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard))
                        state->OnKeyPressed((int)c);
                }
...

The most likely reason I can imagine is if perhaps X-Window or GLFW alter mods at the time character submission.
AFAIK when pressing Alt-GR + 7 both CTRL and ALT should be reported as pressed?
Can you confirm it in Demo->Inputs section?

You may also use Demo->Tools->Debug Log and click "IO" to visualize events.

Thank you! and happy new year!

@AlexanderKaschta
Copy link
Author

Thank you for the quick response and a Happy New Year!

I completely forgot about the IO config flags and checked the ImGuiConfigFlags_NavEnableKeyboard including the debug instructions. It makes a difference.

When it's enabled (like in the example_glfw_opengl3 from the docking branch),

ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;       // Enable Keyboard Controls

I'm unable to enter the the characters which include the Alt-Gr flag. I've noticed in debugging on my Linux machine, that your referenced part of the InputText() doesn't get called as the surrounding if (g.ActiveId == id) is evaluated to false.

When I disable the flag I'm successfully able to enter the characters on Linux. I've validated this in debugging on my Linux machine that in this case the if (g.ActiveId == id) check if evaluated to true and and the matching code snippet is executed.

Enabling/disabling the ImGuiConfigFlags_NavEnableKeyboard flag on Windows makes on difference on the ability to enter characters with the Alt-Gr-modifier as it always works.

AFAIK when pressing Alt-GR + 7 both CTRL and ALT should be reported as pressed?
Can you confirm it in Demo->Inputs section?

Under keys down only RightAlt and 7 are reported, key mods only reports ALT for a short time. This is output of the Demo->Tools->Debug Log for a Alt-GR + 7 press:

[37314] Processed: Key "ModAlt" Down
[37314] Processed: Key "RightAlt" Down
[37325] Processed: Key "ModAlt" Up
[37325] Processed: Key "7" Down
[37326] Processed: Text: { (U+0000007B)
[37332] Processed: Key "7" Up
[37336] Processed: Key "RightAlt" Up

Ctrl and Alt in the debug printf statement are always 0.

@ocornut
Copy link
Owner

ocornut commented Jan 3, 2023

Going to investigate, but in the meanwhile: could you try with the SDL backend, both in latest version and with a version older than 1.86 ? See if the bug happens with either.

@ocornut
Copy link
Owner

ocornut commented Jan 3, 2023

It seems incorrect that ModAlt is released before the 7 key and { character are emitted.

GLFW Bug/Discussion: glfw/glfw#1630 + glfw/glfw#2155

Prior to the 1.87 work we did extrapolate modifiers from keys:

    // Modifiers are not reliable across systems
    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];
#ifdef _WIN32
    io.KeySuper = false;
#else
    io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER];
#endif

Further commits e.g. ecd212c massaged it to e.g.

static void ImGui_ImplGlfw_UpdateKeyModifiers()
{
    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
    ImGuiIO& io = ImGui::GetIO();
    io.KeyShift = ((glfwGetKey(bd->Window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) || (glfwGetKey(bd->Window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS));
    io.KeyCtrl  = ((glfwGetKey(bd->Window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS) || (glfwGetKey(bd->Window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS));
    io.KeyAlt   = ((glfwGetKey(bd->Window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS) || (glfwGetKey(bd->Window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS));
    io.KeySuper = ((glfwGetKey(bd->Window, GLFW_KEY_LEFT_SUPER) == GLFW_PRESS) || (glfwGetKey(bd->Window, GLFW_KEY_RIGHT_SUPER) == GLFW_PRESS));
}

And then commit 0755767 started switching to relying on mods provided by GLFW, which probably introduced the bug.
With later commit 1ad8ad6 we somehow half-fixed an issue but this seems remaining.


Looking for the source of "// Modifiers are not reliable across systems" comment I tracked it to 71429d3 (very old) and the code itself to 4b7be31 (very old) which has no related issue/comments.

But TL;DR;

A possible fix may be to change ImGui_ImplGlfw_UpdateKeyModifiers() to use keys:

static void ImGui_ImplGlfw_UpdateKeyModifiers(int mods)
{
    (void)mods; // UNUSED
    ImGuiIO& io = ImGui::GetIO();
    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
    io.AddKeyEvent(ImGuiMod_Ctrl, (glfwGetKey(bd->Window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS) || (glfwGetKey(bd->Window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS));
    io.AddKeyEvent(ImGuiMod_Shift,  (glfwGetKey(bd->Window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) || (glfwGetKey(bd->Window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS));
    io.AddKeyEvent(ImGuiMod_Alt,   (glfwGetKey(bd->Window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS) || (glfwGetKey(bd->Window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS));
    io.AddKeyEvent(ImGuiMod_Super, (glfwGetKey(bd->Window, GLFW_KEY_LEFT_SUPER) == GLFW_PRESS) || (glfwGetKey(bd->Window, GLFW_KEY_RIGHT_SUPER) == GLFW_PRESS));
}

Can you test this?
If we adopt this we can remove the mods parameter and simply calling code.

@ocornut
Copy link
Owner

ocornut commented Jan 3, 2023

One problem with aforementioned change is:

  • We increase an already existing gap between backends in term of how Mods are reported but a few very specific cases, including Alt-GR on German layout (note that Alt-GR on most other layouts don't have this). There are other very subtle cases I'd rather not think about (sticky keys on Windows?) that probably don't matter.
  • In Win32 and SDL and GLFW backend in German Layout, holding ALT-GR reports RightAlt KEY and Alt MOD and Ctrl MOD.
  • But on GLFW on Linux, pressing a key e.g. 7 releases Alt Mod.?? IHMO this is a bug in GLFW.
  • With aforementioned fix in GLFW backend, holding ALT+GR will report RightAlt KEY and Alt MOD but not Ctrl MOD.
  • One could argue it is desirable to not report Ctrl MOD as to lift burden on app code which may have issues for German users, but if we decide to lift this burden it would arguably be saner to lift it for all backends, not just GLFW.

One possible thing is we apply the change above (if it works) making GLFW backends slightly inconsistent, hoping it doesn't matter. Another possible thing is we conditionally only apply it on Linux. I would think it is better to it everywhere so we are most likely to detect issues (Linux+German+GLFW is a rarer combination that German+GLFW). And if we end up finding another issue we can decide if we want Linux only workaround later.

@AlexanderKaschta
Copy link
Author

Sure, I will test it tonight.

@AlexanderKaschta
Copy link
Author

I've done some quick testing with your proposed fix to the ImGui_ImplGlfw_UpdateKeyModifiers() with the following results:

  • On Ubuntu the fix works and I'm able to enter all characters with the Alt-Gr modifier with ImGuiConfigFlags_NavEnableKeyboard enabled, which previously had issues. It also works when ImGuiConfigFlags_NavEnableKeyboard is disabled. The resulting logs seems right on the first look
[47704] Processed: Key "ModAlt" Down
[47704] Processed: Key "RightAlt" Down
[47710] Processed: Key "Q" Down
[47711] Processed: Text: @ (U+00000040)
[47718] Processed: Key "Q" Up
[47719] Processed: Key "ModAlt" Up
[47719] Processed: Key "RightAlt" Up 
  • I've also tested the proposed fix under Windows and it seems to work there too.

I'm aware, that the Alt-Gr key and functionality is something special due to language and keyboard layout, where other regions don't have it or it's behavior is different. I'm honest, that I would like to see a general GLFW fix for it, as this seems to be a lower problem and (I guess) it also affects other people then me. I don't know, if I should report this issue to GLFW, as looking into the issues glfw/glfw#1630 and glfw/glfw#1502 suggests, that It's a known problem. Reading those two issues I'm still unclear what the current progress / status of those issues are.

When I have some spare time the coming days I will still try the SDL backend (with the two ImGui versions) on Linux and see how that backend behaves. Initially I've chosen the GLFW backend as it's smaller than SDL, I have no need for audio and the support for the desktop platforms is enough for me as the goal was to create a cross platform GUI application that looks quite same on Windows & Linux and isn't bloated (like Qt).

@ocornut ocornut added the bug label Jan 4, 2023
ocornut added a commit that referenced this issue Jan 4, 2023
@ocornut
Copy link
Owner

ocornut commented Jan 4, 2023

The fix essentially gets us back to mods polling we used before January 2022, I am fine with it.

Pushed fix as 1f6e62a

I think it may be worth reporting this to GLFW separately I am not sure 100% this is the same as their other issues.

Thanks for reporting and helping to look into that. Hopefully it won't bite us back again :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants