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

sokol_app: x11: Make sapp_event.key_code layout independant #1078

Closed
wants to merge 1 commit into from

Conversation

marekmaskarinec
Copy link

Currently on Linux, values reported in sapp_event.key_code depend on the keyboard layout, which is undesirable and inconsistent with other platforms (tested on Windows and emsc). With this PR, keys are reported according to the us qwerty layout.

@marekmaskarinec marekmaskarinec changed the title sokol_app: linux: Make sapp_event.key_code layout independant sokol_app: x11: Make sapp_event.key_code layout independant Jul 11, 2024
@floooh
Copy link
Owner

floooh commented Jul 12, 2024

Thanks! Looks like a nice and simple fix. I'll give it a whirl later today, or latest on Sunday on my Linux laptop.

@floooh floooh self-assigned this Jul 12, 2024
@floooh
Copy link
Owner

floooh commented Jul 12, 2024

One minor nitpick, but I think I'll just change that during testing and merging: I'd like to move the one-time call to XkbGetKeyboardByName into the initialization somewhere around here:

sokol/sokol_app.h

Line 11133 in 7b20c19

XkbSetDetectableAutoRepeat(_sapp.x11.display, true, NULL);

Do you know if the return value of XkbGetKeyboardByName needs to be freed via XFree()? The documentation doesn't mention anything about ownership unfortunately: https://www.x.org/releases/X11R7.5/doc/man/man3/XkbGetKeyboardByName.3.html

@floooh
Copy link
Owner

floooh commented Jul 12, 2024

Ah ok, there's a dedicated free function XkbFreeKeyboard.

Btw, GLFW uses a different approach by dynamically building a mapping table:

https://github.com/glfw/glfw/blob/b35641f4a3c62aa86a0b3c983d163bc0fe36026d/src/x11_init.c#L213-L436

...but your approach is definitely less code.

@floooh
Copy link
Owner

floooh commented Jul 12, 2024

NOTE: I was fooled by the actual issue that sokol_app.h always uses the key mapping that's the first in the 'system settings', see: #1080

Hmmm.... I just checked the master branch on my Ubuntu laptop, and there it already works as expected (tested with the events-sapp sample):

  • setting the keyboard layout to German, and pressing the Y key (at the bottom left on a German keyboard, same as the Z key on an English keyboard), I get SAPP_KEYCODE_Z for the KEY events, and the char code 0x79 (which is the ASCII/UNICODE code for y) in the CHAR event
  • setting the keyboard layout to US English (even while the app keeps running) and pressing the Y key, I also get SAPP_KEYCODE_Z for the KEY events, and the char code 0x7A (which is the ASCII/UNICODE code for z) in the CHAR event

...so at least on my setup (a vanilla Ubuntu install with KDE Plasma desktop session via XWayland), it already works as expected, the sokol-app KEY events are keyboard layout independent, and the CHAR events are layout dependent.

...I'll try a native X11 session next...

...same behaviour on a native X11 KDE session.

I'd like to figure out why your setup behaves differently before applying the change, and ideally also be able to reproduce your behaviour. What's your distro and desktop environment?

@skejeton
Copy link
Contributor

Try checking it with colemak/dvorak layouts.

@floooh
Copy link
Owner

floooh commented Jul 12, 2024

Try checking it with colemak/dvorak layouts.

Would the PR fix this? As far as I understand it, it just enforces the US layout when translating key codes?

@skejeton
Copy link
Contributor

I think this is supposed to treat any key press as a scancode on the US QWERTY keyboard regardless of the layout. So QWERTY keys for WASD on Colemak would match up to WARS and <AOE on Dvorak.

@floooh
Copy link
Owner

floooh commented Jul 12, 2024

Ah ok, now I have something to go with:

It looks like sokol_app.h always uses the first keyboard layout in the settings list... for instance when I move the German layout to the top of the list in my system settings, I get the KEY events for the German keyboard layout, no matter what layout is currently active. Previously I had the US layout at the top of the list, which fooled me.

I'll try the PR (but will move the static one-time init into the initialization phase.

@floooh
Copy link
Owner

floooh commented Jul 12, 2024

Hmm, the fix doesn't work on my machine, it always hits the assertion after the XkbGetKeyboardByName call (e.g. that function returns a null pointer).

@floooh
Copy link
Owner

floooh commented Jul 12, 2024

Why does X11 suck so much... I guess GLFW has the correct solution, but it's a gnarly piece of code with fallbacks:

https://github.com/glfw/glfw/blob/b35641f4a3c62aa86a0b3c983d163bc0fe36026d/src/x11_init.c#L43-L436

@floooh
Copy link
Owner

floooh commented Jul 12, 2024

I wrote a proper ticket for the problem, since the solution doesn't seem to be trivial:

#1080

@floooh
Copy link
Owner

floooh commented Jul 12, 2024

Turns out the assert I'm seeing happens on a Wayland session with XWayland, a native X11 desktop session works fine... so it looks like XWayland doesn't fully emulate X11. Nevertheless we'll need to find a solution that also works on XWayland.

On an X11 desktop session, the fix in the PR works here btw (e.g. I have the German keyboard layout first in the list, and the German Y key returns SAPP_KEYCODE_Z.

@floooh
Copy link
Owner

floooh commented Jul 12, 2024

GLFW was running into the same issue with XWayland: glfw/glfw#389

If it's a bug in XWayland they're certainly not in a hurry to fix it :/

@floooh
Copy link
Owner

floooh commented Jul 12, 2024

I will try to look into the issue on Monday. I guess I will just copy the GLFW solution - even when it's a hefty piece of code, but we would probably just end up with the same solution after running into all the same traps again ;)

Signed-off-by: Marek Maškarinec <marek@mrms.cz>
@floooh
Copy link
Owner

floooh commented Jul 13, 2024

Thanks for the additional fix @marekmaskarinec, but since the call to XkbGetKeyboardByName doesn't work on XWayland I won't be able to merge this PR anyway. I'll try to integrate GLFW's solution of building a lookup table dynamically at startup (unless you want to volunteer ;)

@marekmaskarinec
Copy link
Author

I'd be up for helping, but I can only get to it Monday. Is that okay with you?

@floooh
Copy link
Owner

floooh commented Jul 14, 2024

I'd be up for helping, but I can only get to it Monday. Is that okay with you?

No worries, I'll try to start this afternoon. Also, since it's an actual and longstanding bug I kinda feel responsible for the fix ;)

@floooh
Copy link
Owner

floooh commented Jul 14, 2024

New attempt here: #1081

I would appreciate if you could give this a whirl before merging (I'll do a couple more tests on KDE with XWayland, and native X11 session, and would like to merge tomorrow (Monday).

@floooh
Copy link
Owner

floooh commented Jul 16, 2024

Ok, closing the PR in favour of #1081 (which I just merged).

Still, many thanks @marekmaskarinec for kicking off the fix and providing a PR (even if that wasn't used in the end).

@floooh floooh closed this Jul 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants