None of the text box dialogs allow input (linux-only issue?)
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.
So when you click on the text box you can't edit it? It works fine on windows.
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...
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
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!
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.
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.
fix may be striaght-forward because
KeyboardKeyis just a int-backed enum, so maybe we can probably pass it right intoConvert.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.
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.
^ 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!
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,
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.
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.