Wayland: Replace _glfwKeySym2Unicode with xkbcommon

libxkbcommon already provides functions to convert keysyms to codepoints
and UTF-8. The library has offered these functions since 0.5.0[1], so
using them won't cause any compatibility problems.

[1] https://xkbcommon.org/doc/0.5.0/group__keysyms.html

Closes #2444
This commit is contained in:
LocalSpook
2023-12-10 05:54:11 -07:00
committed by Camilla Löwy
parent a576a56a8d
commit 21fea01161
4 changed files with 26 additions and 17 deletions

View File

@@ -1192,8 +1192,8 @@ static void inputText(_GLFWwindow* window, uint32_t scancode)
if (xkb_state_key_get_syms(_glfw.wl.xkb.state, keycode, &keysyms) == 1)
{
const xkb_keysym_t keysym = composeSymbol(keysyms[0]);
const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
if (codepoint != GLFW_INVALID_CODEPOINT)
const uint32_t codepoint = xkb_keysym_to_utf32(keysym);
if (codepoint != 0)
{
const int mods = _glfw.wl.xkb.modifiers;
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
@@ -2721,23 +2721,23 @@ const char* _glfwGetScancodeNameWayland(int scancode)
return NULL;
}
const uint32_t codepoint = _glfwKeySym2Unicode(keysyms[0]);
if (codepoint == GLFW_INVALID_CODEPOINT)
// WORKAROUND: xkb_keysym_to_utf8() requires the third parameter (size of the output buffer)
// to be at least 7 (6 bytes + a null terminator), because it was written when UTF-8
// sequences could be up to 6 bytes long. The _glfw.wl.keynames buffers are only 5 bytes
// long, because UTF-8 sequences are now limited to 4 bytes and no codepoints were ever assigned
// that needed more than that. To work around this, we first copy to a temporary buffer.
//
// See: https://github.com/xkbcommon/libxkbcommon/issues/418
char temp_buffer[7];
const int bytes_written = xkb_keysym_to_utf8(keysyms[0], temp_buffer, sizeof(temp_buffer));
if (bytes_written <= 0 || bytes_written > 5)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to retrieve codepoint for key name");
"Wayland: Failed to encode keysym as UTF-8");
return NULL;
}
memcpy(_glfw.wl.keynames[key], temp_buffer, bytes_written);
const size_t count = _glfwEncodeUTF8(_glfw.wl.keynames[key], codepoint);
if (count == 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to encode codepoint for key name");
return NULL;
}
_glfw.wl.keynames[key][count] = '\0';
return _glfw.wl.keynames[key];
}