Civ2-clone icon indicating copy to clipboard operation
Civ2-clone copied to clipboard

None of the text box dialogs allow input (linux-only issue?)

Open hoodlm opened this issue 2 months ago • 10 comments

Unless other people have noticed this I suspect this is a bug/issue specific to raylibUI in Linux.

Any of the textbox dialogs (custom leader name, custom city name, etc.) do not allow modifying the default text.

hoodlm avatar Nov 03 '25 03:11 hoodlm

So when you click on the text box you can't edit it? It works fine on windows.

axx0 avatar Nov 03 '25 16:11 axx0

Can you give more details of this issue? I just Tested on Bazzite and it was working I could rename my leader and tribe etc...

reubene avatar Nov 05 '25 09:11 reubene

So when you click on the text box you can't edit it? It works fine on windows.

Yeah it's very weird. I can backspace(!) but can't enter any characters. Using ubuntu 24.04.3, fairly stock (Gnome 46, etc.)

Demo shows it launching from dotnet run but i get the same behavior launching from Rider IDE. I will poke around in the debugger and see if I can figure out any other clues.

https://github.com/user-attachments/assets/063db036-9b9a-442a-b084-dae262a17bd6

hoodlm avatar Nov 11 '25 03:11 hoodlm

OK, here i pressed 'a' in the leader name dialog. Note that key (as in, switch (key) on line 110 of TextBox.cs) is KeyboardKey.A but Input.GetCharPressed() yields a 0!

Image Image

hoodlm avatar Nov 11 '25 03:11 hoodlm

ok if I really bang on my keyboard, about 1-in-20 characters get through. :) So I suspect it's some kind of race condition between GetCharPressed() and whatever dispatches the OnKeyPressed hook. fix may be striaght-forward because KeyboardKey is just a int-backed enum, so maybe we can probably pass it right into Convert.ToChar. I'll test this out and send a PR if it works.

hoodlm avatar Nov 11 '25 04:11 hoodlm

OK, it's not quite as simple as that, i tried:

-  _text = _text.Insert(_editPosition, Convert.ToChar(charPressed).ToString());
+  _text = _text.Insert(_editPosition, Convert.ToChar(key).ToString());

my letters all get through, but as UPPERCASE letters only 😆

so, needs more research. happy to test any ideas if anyone thinks of anything.

hoodlm avatar Nov 11 '25 04:11 hoodlm

fix may be striaght-forward because KeyboardKey is just a int-backed enum, so maybe we can probably pass it right into Convert.ToChar.

Yeah that won't do. KeyboardKey just gives you info which key on the keyboard you pressed. For 'a' it gives int=65 which happens to be 'A' in unicode, but that's just how raylib is programmed. I mean you could implement some messy solution by also monitoring if Shift is pressed and state of CapsLock and then determine if it's 'a' or 'A', but that's just overly complicated.

Basically Input.GetCharPressed() yielding 0 even though you pressed 'a' is wrong and is probably a linux bug with this method in either Raylib-Csharp wrapper or in raylib itself. I would first post an issue in the former repo.

axx0 avatar Nov 14 '25 20:11 axx0

Progress update / a bit of rubberducking.

I've got a simple repro of the issue. This code is structurally equivalent to this loop in BaseScreen.ControlEvents and Textbox.OnKeyPressed.

using Raylib_CSharp.Interact;
using Raylib_CSharp.Rendering;
using Raylib_CSharp.Windowing;

Window.Init(1280, 800, "repro");
KeyboardKey[] keys = (KeyboardKey[])Enum.GetValues(typeof(KeyboardKey));
while (true)
{
    foreach (var key in keys)
    {
        if (Input.IsKeyPressed(key))
        {
            int character = Input.GetCharPressed();
            String msg;
            if (character > 0)
            {
                msg = String.Format("Loop on key {0}, getCharPressed HIT {1}", key, Convert.ToChar(character));
            } else {
                msg = String.Format("Loop on key {0}, no GetCharPressed ({1})", key, character);
            }
            Console.WriteLine(msg);
        }
    }
    Graphics.EndDrawing();
}

as before, if I really smash the keyboard, i might get 1-in-50 keypresses through:

...
Loop on key S, no GetCharPressed (0)
Loop on key F, no GetCharPressed (0)
Loop on key G, no GetCharPressed (0)
Loop on key F, no GetCharPressed (0)
Loop on key S, getCharPressed HIT f
Loop on key D, no GetCharPressed (0)
Loop on key G, no GetCharPressed (0)
Loop on key A, no GetCharPressed (0)
Loop on key S, no GetCharPressed (0)
Loop on key D, no GetCharPressed (0)
Loop on key F, no GetCharPressed (0)
...

If I comment out the check for Input.GetCharPressed() then it stops missing keypresses:

while (true)
{
    foreach (var key in keys)
    {
        // if (Input.IsKeyPressed(key))
        {
            int character = Input.GetCharPressed();
            String msg;
            if (character > 0)
            {
                msg = String.Format("Loop on key {0}, getCharPressed HIT {1}", key, Convert.ToChar(character));
                Console.WriteLine(msg);
            } else {
                // msg = String.Format("Loop on key {0}, no GetCharPressed ({1})", key, character);
            }
        }
    }
    Graphics.EndDrawing();
}

and interestingly it always logs it on the first pass in the loop (Null or key 0 is the first element of the keys array)

...
Loop on key Null, getCharPressed HIT A
Loop on key Null, getCharPressed HIT B
Loop on key Null, getCharPressed HIT D
Loop on key Null, getCharPressed HIT S
Loop on key Null, getCharPressed HIT C
Loop on key Null, getCharPressed HIT S
Loop on key Null, getCharPressed HIT C
Loop on key Null, getCharPressed HIT S
...

So... to me this smells like IsKeyPressed is draining the CharPressed queue.

I still want to go a level deeper and see if I can reproduce it in a C++ Raylib program. Basically, triage whether it's an issue in CSharp-Raylib bindings vs in Raylib itself before I report a bug one place or the other.

hoodlm avatar Dec 10 '25 02:12 hoodlm

^ Would be very interesting if someone who isn't having any problems with Civ2-clone could run that first code block on their machine and confirm it works normally!

hoodlm avatar Dec 10 '25 02:12 hoodlm

I ran your example on Bazzite and MacOS. I didn't see the issue you're describing on either. I did see a race condition though when keys are pressed in quick succession or simultaneously then Input.getCharPressed doesn't return the char that matches key.

We're 100% doing something wrong here,

reubene avatar Dec 15 '25 03:12 reubene

since this is mostly a me-problem i'll take an earnest shot at re-plumbing this. I have a bit of time off work so now's a good time.

I suspect the devil-in-the-details will be correctly handling chorded shortcuts (e.g., differentiate S from CTRL-S), handling arrow keys correctly in the text box controls, etc.

hoodlm avatar Dec 28 '25 23:12 hoodlm

See PR above ^

Here's another minimal code segment that illustrates what i think the problem was:

using Raylib_CSharp.Interact;
using Raylib_CSharp.Rendering;
using Raylib_CSharp.Windowing;

Window.Init(1280, 800, "repro");
while (true)
{
    String charPressed = Convert.ToChar(Input.GetCharPressed()).ToString();
    KeyboardKey keyPressed = (KeyboardKey) Input.GetKeyPressed();
    if (charPressed == char.MinValue.ToString())
    {
        charPressed = "NULL";
    }
    Console.WriteLine($"Key pressed: {keyPressed}, char pressed: {charPressed}");
    
    Thread.Sleep(200);
    Graphics.EndDrawing();
}

this results in:

...
Key pressed: Null, char pressed: NULL
Key pressed: F, char pressed: NULL
Key pressed: Null, char pressed: f
Key pressed: Null, char pressed: NULL
Key pressed: Null, char pressed: NULL
Key pressed: Null, char pressed: NULL
Key pressed: F, char pressed: NULL
Key pressed: Null, char pressed: f
Key pressed: Null, char pressed: NULL
Key pressed: Null, char pressed: NULL
...

So the TL;DR of how i fixed it: decouple GetCharPressed and GetKeyPressed into separate event handlers.

hoodlm avatar Dec 29 '25 04:12 hoodlm