Update glfw from upstream
Includes proper fix for Wayland key repeat
This commit is contained in:
parent
69f3ceb903
commit
bfa53d4b45
20
glfw/glfw.py
20
glfw/glfw.py
@ -22,20 +22,6 @@ def wayland_protocol_file_name(base, ext='c'):
|
|||||||
return 'wayland-{}-client-protocol.{}'.format(base, ext)
|
return 'wayland-{}-client-protocol.{}'.format(base, ext)
|
||||||
|
|
||||||
|
|
||||||
def find_epoll_shim():
|
|
||||||
cflags, ldflags, libs = [], [], []
|
|
||||||
for candidate in '/usr/local/include/libepoll-shim /usr/include/libepoll-shim /usr/local/include /usr/include'.split():
|
|
||||||
if os.path.exists(os.path.join(candidate, 'sys/timerfd.h')):
|
|
||||||
cflags.append('-I' + candidate)
|
|
||||||
break
|
|
||||||
for candidate in '/usr/local/lib /usr/lib'.split():
|
|
||||||
if os.path.exists(os.path.join(candidate, 'libepoll-shim.so')):
|
|
||||||
ldflags.append('-L' + candidate)
|
|
||||||
libs.append('-lepoll-shim')
|
|
||||||
break
|
|
||||||
return cflags, ldflags, libs
|
|
||||||
|
|
||||||
|
|
||||||
def init_env(env, pkg_config, at_least_version, module='x11'):
|
def init_env(env, pkg_config, at_least_version, module='x11'):
|
||||||
ans = env.copy()
|
ans = env.copy()
|
||||||
ans.cflags = [
|
ans.cflags = [
|
||||||
@ -77,12 +63,6 @@ def init_env(env, pkg_config, at_least_version, module='x11'):
|
|||||||
for p in ans.wayland_protocols:
|
for p in ans.wayland_protocols:
|
||||||
ans.sources.append(wayland_protocol_file_name(p))
|
ans.sources.append(wayland_protocol_file_name(p))
|
||||||
ans.all_headers.append(wayland_protocol_file_name(p, 'h'))
|
ans.all_headers.append(wayland_protocol_file_name(p, 'h'))
|
||||||
if is_bsd:
|
|
||||||
epoll_cflags, epoll_libdirs, epoll_libs = find_epoll_shim()
|
|
||||||
if not epoll_cflags + epoll_libdirs:
|
|
||||||
raise Exception('Failed to find the epoll-shim package, needed to build the GLFW Wayland backend')
|
|
||||||
ans.cflags.extend(epoll_cflags)
|
|
||||||
ans.ldpaths.extend(epoll_libdirs + epoll_libs)
|
|
||||||
for dep in 'wayland-egl wayland-client wayland-cursor xkbcommon'.split():
|
for dep in 'wayland-egl wayland-client wayland-cursor xkbcommon'.split():
|
||||||
ans.cflags.extend(pkg_config(dep, '--cflags-only-I'))
|
ans.cflags.extend(pkg_config(dep, '--cflags-only-I'))
|
||||||
ans.ldpaths.extend(pkg_config(dep, '--libs'))
|
ans.ldpaths.extend(pkg_config(dep, '--libs'))
|
||||||
|
|||||||
@ -57,6 +57,7 @@
|
|||||||
"wl_platform.h",
|
"wl_platform.h",
|
||||||
"posix_time.h",
|
"posix_time.h",
|
||||||
"posix_thread.h",
|
"posix_thread.h",
|
||||||
|
"xkb_glfw.h",
|
||||||
"xkb_unicode.h",
|
"xkb_unicode.h",
|
||||||
"egl_context.h",
|
"egl_context.h",
|
||||||
"osmesa_context.h",
|
"osmesa_context.h",
|
||||||
|
|||||||
374
glfw/wl_init.c
vendored
374
glfw/wl_init.c
vendored
@ -32,7 +32,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/timerfd.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
|
||||||
@ -350,16 +349,7 @@ static void keyboardHandleKeymap(void* data,
|
|||||||
int fd,
|
int fd,
|
||||||
uint32_t size)
|
uint32_t size)
|
||||||
{
|
{
|
||||||
struct xkb_keymap* keymap;
|
|
||||||
struct xkb_state* state;
|
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
struct xkb_compose_table* composeTable;
|
|
||||||
struct xkb_compose_state* composeState;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char* mapStr;
|
char* mapStr;
|
||||||
const char* locale;
|
|
||||||
|
|
||||||
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
|
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
|
||||||
{
|
{
|
||||||
@ -372,78 +362,10 @@ static void keyboardHandleKeymap(void* data,
|
|||||||
close(fd);
|
close(fd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
xkb_glfw_compile_keymap(mapStr);
|
||||||
keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context,
|
|
||||||
mapStr,
|
|
||||||
XKB_KEYMAP_FORMAT_TEXT_V1,
|
|
||||||
0);
|
|
||||||
munmap(mapStr, size);
|
munmap(mapStr, size);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
if (!keymap)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Wayland: Failed to compile keymap");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
state = xkb_state_new(keymap);
|
|
||||||
if (!state)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Wayland: Failed to create XKB state");
|
|
||||||
xkb_keymap_unref(keymap);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look up the preferred locale, falling back to "C" as default.
|
|
||||||
locale = getenv("LC_ALL");
|
|
||||||
if (!locale)
|
|
||||||
locale = getenv("LC_CTYPE");
|
|
||||||
if (!locale)
|
|
||||||
locale = getenv("LANG");
|
|
||||||
if (!locale)
|
|
||||||
locale = "C";
|
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
composeTable =
|
|
||||||
xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
|
|
||||||
XKB_COMPOSE_COMPILE_NO_FLAGS);
|
|
||||||
if (composeTable)
|
|
||||||
{
|
|
||||||
composeState =
|
|
||||||
xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
|
|
||||||
xkb_compose_table_unref(composeTable);
|
|
||||||
if (composeState)
|
|
||||||
_glfw.wl.xkb.composeState = composeState;
|
|
||||||
else
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Wayland: Failed to create XKB compose state");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Wayland: Failed to create XKB compose table");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
|
||||||
xkb_state_unref(_glfw.wl.xkb.state);
|
|
||||||
_glfw.wl.xkb.keymap = keymap;
|
|
||||||
_glfw.wl.xkb.state = state;
|
|
||||||
|
|
||||||
_glfw.wl.xkb.controlMask =
|
|
||||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control");
|
|
||||||
_glfw.wl.xkb.altMask =
|
|
||||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
|
|
||||||
_glfw.wl.xkb.shiftMask =
|
|
||||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
|
|
||||||
_glfw.wl.xkb.superMask =
|
|
||||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
|
|
||||||
_glfw.wl.xkb.capsLockMask =
|
|
||||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Lock");
|
|
||||||
_glfw.wl.xkb.numLockMask =
|
|
||||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod2");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyboardHandleEnter(void* data,
|
static void keyboardHandleEnter(void* data,
|
||||||
@ -482,15 +404,6 @@ static void keyboardHandleLeave(void* data,
|
|||||||
_glfwInputWindowFocus(window, GLFW_FALSE);
|
_glfwInputWindowFocus(window, GLFW_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int toGLFWKeyCode(uint32_t key)
|
|
||||||
{
|
|
||||||
if (key < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
|
|
||||||
return _glfw.wl.keycodes[key];
|
|
||||||
|
|
||||||
return GLFW_KEY_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
|
static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
|
||||||
{
|
{
|
||||||
if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
|
if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
|
||||||
@ -510,9 +423,8 @@ static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
|
|||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static GLFWbool inputChar(_GLFWwindow* window, uint32_t key)
|
static void inputChar(_GLFWwindow* window, uint32_t key, GLFWbool *shouldRepeat)
|
||||||
{
|
{
|
||||||
uint32_t code, numSyms;
|
uint32_t code, numSyms;
|
||||||
long cp;
|
long cp;
|
||||||
@ -521,24 +433,23 @@ static GLFWbool inputChar(_GLFWwindow* window, uint32_t key)
|
|||||||
|
|
||||||
code = key + 8;
|
code = key + 8;
|
||||||
numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms);
|
numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms);
|
||||||
|
*shouldRepeat = xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, code);
|
||||||
|
|
||||||
if (numSyms == 1)
|
if (numSyms == 1)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
sym = composeSymbol(syms[0]);
|
sym = composeSymbol(syms[0]);
|
||||||
#else
|
|
||||||
sym = syms[0];
|
|
||||||
#endif
|
|
||||||
cp = _glfwKeySym2Unicode(sym);
|
cp = _glfwKeySym2Unicode(sym);
|
||||||
if (cp != -1)
|
if (cp != -1)
|
||||||
{
|
{
|
||||||
const int mods = _glfw.wl.xkb.modifiers;
|
const int mods = _glfw.wl.xkb.modifiers;
|
||||||
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
|
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
|
||||||
|
if (*shouldRepeat) {
|
||||||
|
_glfw.wl.keyRepeatInfo.codepoint = cp;
|
||||||
|
_glfw.wl.keyRepeatInfo.plain = plain;
|
||||||
|
}
|
||||||
_glfwInputChar(window, cp, mods, plain);
|
_glfwInputChar(window, cp, mods, plain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, syms[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyboardHandleKey(void* data,
|
static void keyboardHandleKey(void* data,
|
||||||
@ -551,34 +462,33 @@ static void keyboardHandleKey(void* data,
|
|||||||
int keyCode;
|
int keyCode;
|
||||||
int action;
|
int action;
|
||||||
_GLFWwindow* window = _glfw.wl.keyboardFocus;
|
_GLFWwindow* window = _glfw.wl.keyboardFocus;
|
||||||
GLFWbool shouldRepeat;
|
|
||||||
struct itimerspec timer = {};
|
|
||||||
|
|
||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
keyCode = toGLFWKeyCode(key);
|
keyCode = xkb_glfw_to_glfw_key_code(key);
|
||||||
action = state == WL_KEYBOARD_KEY_STATE_PRESSED
|
action = state == WL_KEYBOARD_KEY_STATE_PRESSED
|
||||||
? GLFW_PRESS : GLFW_RELEASE;
|
? GLFW_PRESS : GLFW_RELEASE;
|
||||||
|
_glfw.wl.keyRepeatInfo.nextRepeatAt = 0;
|
||||||
|
_glfw.wl.keyRepeatInfo.codepoint = -1;
|
||||||
|
|
||||||
_glfwInputKey(window, keyCode, key, action,
|
_glfwInputKey(window, keyCode, key, action,
|
||||||
_glfw.wl.xkb.modifiers);
|
_glfw.wl.xkb.modifiers);
|
||||||
|
|
||||||
if (action == GLFW_PRESS)
|
if (action == GLFW_PRESS)
|
||||||
{
|
{
|
||||||
shouldRepeat = inputChar(window, key);
|
GLFWbool shouldRepeat = GLFW_FALSE;
|
||||||
|
inputChar(window, key, &shouldRepeat);
|
||||||
|
|
||||||
if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0)
|
if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0)
|
||||||
{
|
{
|
||||||
_glfw.wl.keyboardLastKey = keyCode;
|
_glfw.wl.keyRepeatInfo.glfwKeyCode = keyCode;
|
||||||
_glfw.wl.keyboardLastScancode = key;
|
_glfw.wl.keyRepeatInfo.scancode = key;
|
||||||
timer.it_interval.tv_sec = _glfw.wl.keyboardRepeatRate / 1000;
|
_glfw.wl.keyRepeatInfo.isFirstRepeat = GLFW_TRUE;
|
||||||
timer.it_interval.tv_nsec = (_glfw.wl.keyboardRepeatRate % 1000) * 1000000;
|
_glfw.wl.keyRepeatInfo.nextRepeatAt = glfwGetTime() + (double)(_glfw.wl.keyboardRepeatDelay) / 1000.0;
|
||||||
timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000;
|
_glfw.wl.keyRepeatInfo.keyboardFocus = window;
|
||||||
timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyboardHandleModifiers(void* data,
|
static void keyboardHandleModifiers(void* data,
|
||||||
@ -589,41 +499,9 @@ static void keyboardHandleModifiers(void* data,
|
|||||||
uint32_t modsLocked,
|
uint32_t modsLocked,
|
||||||
uint32_t group)
|
uint32_t group)
|
||||||
{
|
{
|
||||||
xkb_mod_mask_t mask;
|
xkb_glfw_update_modifiers(modsDepressed, modsLatched, modsLocked);
|
||||||
unsigned int modifiers = 0;
|
|
||||||
|
|
||||||
if (!_glfw.wl.xkb.keymap)
|
|
||||||
return;
|
|
||||||
|
|
||||||
xkb_state_update_mask(_glfw.wl.xkb.state,
|
|
||||||
modsDepressed,
|
|
||||||
modsLatched,
|
|
||||||
modsLocked,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
group);
|
|
||||||
|
|
||||||
mask = xkb_state_serialize_mods(_glfw.wl.xkb.state,
|
|
||||||
XKB_STATE_MODS_DEPRESSED |
|
|
||||||
XKB_STATE_LAYOUT_DEPRESSED |
|
|
||||||
XKB_STATE_MODS_LATCHED |
|
|
||||||
XKB_STATE_LAYOUT_LATCHED);
|
|
||||||
if (mask & _glfw.wl.xkb.controlMask)
|
|
||||||
modifiers |= GLFW_MOD_CONTROL;
|
|
||||||
if (mask & _glfw.wl.xkb.altMask)
|
|
||||||
modifiers |= GLFW_MOD_ALT;
|
|
||||||
if (mask & _glfw.wl.xkb.shiftMask)
|
|
||||||
modifiers |= GLFW_MOD_SHIFT;
|
|
||||||
if (mask & _glfw.wl.xkb.superMask)
|
|
||||||
modifiers |= GLFW_MOD_SUPER;
|
|
||||||
if (mask & _glfw.wl.xkb.capsLockMask)
|
|
||||||
modifiers |= GLFW_MOD_CAPS_LOCK;
|
|
||||||
if (mask & _glfw.wl.xkb.numLockMask)
|
|
||||||
modifiers |= GLFW_MOD_NUM_LOCK;
|
|
||||||
_glfw.wl.xkb.modifiers = modifiers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
|
|
||||||
static void keyboardHandleRepeatInfo(void* data,
|
static void keyboardHandleRepeatInfo(void* data,
|
||||||
struct wl_keyboard* keyboard,
|
struct wl_keyboard* keyboard,
|
||||||
int32_t rate,
|
int32_t rate,
|
||||||
@ -635,7 +513,6 @@ static void keyboardHandleRepeatInfo(void* data,
|
|||||||
_glfw.wl.keyboardRepeatRate = rate;
|
_glfw.wl.keyboardRepeatRate = rate;
|
||||||
_glfw.wl.keyboardRepeatDelay = delay;
|
_glfw.wl.keyboardRepeatDelay = delay;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static const struct wl_keyboard_listener keyboardListener = {
|
static const struct wl_keyboard_listener keyboardListener = {
|
||||||
keyboardHandleKeymap,
|
keyboardHandleKeymap,
|
||||||
@ -643,9 +520,7 @@ static const struct wl_keyboard_listener keyboardListener = {
|
|||||||
keyboardHandleLeave,
|
keyboardHandleLeave,
|
||||||
keyboardHandleKey,
|
keyboardHandleKey,
|
||||||
keyboardHandleModifiers,
|
keyboardHandleModifiers,
|
||||||
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
|
|
||||||
keyboardHandleRepeatInfo,
|
keyboardHandleRepeatInfo,
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void seatHandleCapabilities(void* data,
|
static void seatHandleCapabilities(void* data,
|
||||||
@ -798,140 +673,6 @@ static const struct wl_registry_listener registryListener = {
|
|||||||
registryHandleGlobalRemove
|
registryHandleGlobalRemove
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create key code translation tables
|
|
||||||
//
|
|
||||||
static void createKeyTables(void)
|
|
||||||
{
|
|
||||||
int scancode;
|
|
||||||
|
|
||||||
memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes));
|
|
||||||
memset(_glfw.wl.scancodes, -1, sizeof(_glfw.wl.scancodes));
|
|
||||||
|
|
||||||
_glfw.wl.keycodes[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;
|
|
||||||
_glfw.wl.keycodes[KEY_1] = GLFW_KEY_1;
|
|
||||||
_glfw.wl.keycodes[KEY_2] = GLFW_KEY_2;
|
|
||||||
_glfw.wl.keycodes[KEY_3] = GLFW_KEY_3;
|
|
||||||
_glfw.wl.keycodes[KEY_4] = GLFW_KEY_4;
|
|
||||||
_glfw.wl.keycodes[KEY_5] = GLFW_KEY_5;
|
|
||||||
_glfw.wl.keycodes[KEY_6] = GLFW_KEY_6;
|
|
||||||
_glfw.wl.keycodes[KEY_7] = GLFW_KEY_7;
|
|
||||||
_glfw.wl.keycodes[KEY_8] = GLFW_KEY_8;
|
|
||||||
_glfw.wl.keycodes[KEY_9] = GLFW_KEY_9;
|
|
||||||
_glfw.wl.keycodes[KEY_0] = GLFW_KEY_0;
|
|
||||||
_glfw.wl.keycodes[KEY_SPACE] = GLFW_KEY_SPACE;
|
|
||||||
_glfw.wl.keycodes[KEY_MINUS] = GLFW_KEY_MINUS;
|
|
||||||
_glfw.wl.keycodes[KEY_EQUAL] = GLFW_KEY_EQUAL;
|
|
||||||
_glfw.wl.keycodes[KEY_Q] = GLFW_KEY_Q;
|
|
||||||
_glfw.wl.keycodes[KEY_W] = GLFW_KEY_W;
|
|
||||||
_glfw.wl.keycodes[KEY_E] = GLFW_KEY_E;
|
|
||||||
_glfw.wl.keycodes[KEY_R] = GLFW_KEY_R;
|
|
||||||
_glfw.wl.keycodes[KEY_T] = GLFW_KEY_T;
|
|
||||||
_glfw.wl.keycodes[KEY_Y] = GLFW_KEY_Y;
|
|
||||||
_glfw.wl.keycodes[KEY_U] = GLFW_KEY_U;
|
|
||||||
_glfw.wl.keycodes[KEY_I] = GLFW_KEY_I;
|
|
||||||
_glfw.wl.keycodes[KEY_O] = GLFW_KEY_O;
|
|
||||||
_glfw.wl.keycodes[KEY_P] = GLFW_KEY_P;
|
|
||||||
_glfw.wl.keycodes[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;
|
|
||||||
_glfw.wl.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
|
|
||||||
_glfw.wl.keycodes[KEY_A] = GLFW_KEY_A;
|
|
||||||
_glfw.wl.keycodes[KEY_S] = GLFW_KEY_S;
|
|
||||||
_glfw.wl.keycodes[KEY_D] = GLFW_KEY_D;
|
|
||||||
_glfw.wl.keycodes[KEY_F] = GLFW_KEY_F;
|
|
||||||
_glfw.wl.keycodes[KEY_G] = GLFW_KEY_G;
|
|
||||||
_glfw.wl.keycodes[KEY_H] = GLFW_KEY_H;
|
|
||||||
_glfw.wl.keycodes[KEY_J] = GLFW_KEY_J;
|
|
||||||
_glfw.wl.keycodes[KEY_K] = GLFW_KEY_K;
|
|
||||||
_glfw.wl.keycodes[KEY_L] = GLFW_KEY_L;
|
|
||||||
_glfw.wl.keycodes[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;
|
|
||||||
_glfw.wl.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
|
|
||||||
_glfw.wl.keycodes[KEY_Z] = GLFW_KEY_Z;
|
|
||||||
_glfw.wl.keycodes[KEY_X] = GLFW_KEY_X;
|
|
||||||
_glfw.wl.keycodes[KEY_C] = GLFW_KEY_C;
|
|
||||||
_glfw.wl.keycodes[KEY_V] = GLFW_KEY_V;
|
|
||||||
_glfw.wl.keycodes[KEY_B] = GLFW_KEY_B;
|
|
||||||
_glfw.wl.keycodes[KEY_N] = GLFW_KEY_N;
|
|
||||||
_glfw.wl.keycodes[KEY_M] = GLFW_KEY_M;
|
|
||||||
_glfw.wl.keycodes[KEY_COMMA] = GLFW_KEY_COMMA;
|
|
||||||
_glfw.wl.keycodes[KEY_DOT] = GLFW_KEY_PERIOD;
|
|
||||||
_glfw.wl.keycodes[KEY_SLASH] = GLFW_KEY_SLASH;
|
|
||||||
_glfw.wl.keycodes[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;
|
|
||||||
_glfw.wl.keycodes[KEY_ESC] = GLFW_KEY_ESCAPE;
|
|
||||||
_glfw.wl.keycodes[KEY_TAB] = GLFW_KEY_TAB;
|
|
||||||
_glfw.wl.keycodes[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;
|
|
||||||
_glfw.wl.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
|
|
||||||
_glfw.wl.keycodes[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;
|
|
||||||
_glfw.wl.keycodes[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;
|
|
||||||
_glfw.wl.keycodes[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;
|
|
||||||
_glfw.wl.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
|
|
||||||
_glfw.wl.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
|
|
||||||
_glfw.wl.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
|
|
||||||
_glfw.wl.keycodes[KEY_MENU] = GLFW_KEY_MENU;
|
|
||||||
_glfw.wl.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
|
|
||||||
_glfw.wl.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
|
|
||||||
_glfw.wl.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
|
|
||||||
_glfw.wl.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
|
|
||||||
_glfw.wl.keycodes[KEY_PAUSE] = GLFW_KEY_PAUSE;
|
|
||||||
_glfw.wl.keycodes[KEY_DELETE] = GLFW_KEY_DELETE;
|
|
||||||
_glfw.wl.keycodes[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;
|
|
||||||
_glfw.wl.keycodes[KEY_ENTER] = GLFW_KEY_ENTER;
|
|
||||||
_glfw.wl.keycodes[KEY_HOME] = GLFW_KEY_HOME;
|
|
||||||
_glfw.wl.keycodes[KEY_END] = GLFW_KEY_END;
|
|
||||||
_glfw.wl.keycodes[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;
|
|
||||||
_glfw.wl.keycodes[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;
|
|
||||||
_glfw.wl.keycodes[KEY_INSERT] = GLFW_KEY_INSERT;
|
|
||||||
_glfw.wl.keycodes[KEY_LEFT] = GLFW_KEY_LEFT;
|
|
||||||
_glfw.wl.keycodes[KEY_RIGHT] = GLFW_KEY_RIGHT;
|
|
||||||
_glfw.wl.keycodes[KEY_DOWN] = GLFW_KEY_DOWN;
|
|
||||||
_glfw.wl.keycodes[KEY_UP] = GLFW_KEY_UP;
|
|
||||||
_glfw.wl.keycodes[KEY_F1] = GLFW_KEY_F1;
|
|
||||||
_glfw.wl.keycodes[KEY_F2] = GLFW_KEY_F2;
|
|
||||||
_glfw.wl.keycodes[KEY_F3] = GLFW_KEY_F3;
|
|
||||||
_glfw.wl.keycodes[KEY_F4] = GLFW_KEY_F4;
|
|
||||||
_glfw.wl.keycodes[KEY_F5] = GLFW_KEY_F5;
|
|
||||||
_glfw.wl.keycodes[KEY_F6] = GLFW_KEY_F6;
|
|
||||||
_glfw.wl.keycodes[KEY_F7] = GLFW_KEY_F7;
|
|
||||||
_glfw.wl.keycodes[KEY_F8] = GLFW_KEY_F8;
|
|
||||||
_glfw.wl.keycodes[KEY_F9] = GLFW_KEY_F9;
|
|
||||||
_glfw.wl.keycodes[KEY_F10] = GLFW_KEY_F10;
|
|
||||||
_glfw.wl.keycodes[KEY_F11] = GLFW_KEY_F11;
|
|
||||||
_glfw.wl.keycodes[KEY_F12] = GLFW_KEY_F12;
|
|
||||||
_glfw.wl.keycodes[KEY_F13] = GLFW_KEY_F13;
|
|
||||||
_glfw.wl.keycodes[KEY_F14] = GLFW_KEY_F14;
|
|
||||||
_glfw.wl.keycodes[KEY_F15] = GLFW_KEY_F15;
|
|
||||||
_glfw.wl.keycodes[KEY_F16] = GLFW_KEY_F16;
|
|
||||||
_glfw.wl.keycodes[KEY_F17] = GLFW_KEY_F17;
|
|
||||||
_glfw.wl.keycodes[KEY_F18] = GLFW_KEY_F18;
|
|
||||||
_glfw.wl.keycodes[KEY_F19] = GLFW_KEY_F19;
|
|
||||||
_glfw.wl.keycodes[KEY_F20] = GLFW_KEY_F20;
|
|
||||||
_glfw.wl.keycodes[KEY_F21] = GLFW_KEY_F21;
|
|
||||||
_glfw.wl.keycodes[KEY_F22] = GLFW_KEY_F22;
|
|
||||||
_glfw.wl.keycodes[KEY_F23] = GLFW_KEY_F23;
|
|
||||||
_glfw.wl.keycodes[KEY_F24] = GLFW_KEY_F24;
|
|
||||||
_glfw.wl.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
|
|
||||||
_glfw.wl.keycodes[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;
|
|
||||||
_glfw.wl.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
|
|
||||||
_glfw.wl.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
|
|
||||||
_glfw.wl.keycodes[KEY_KP0] = GLFW_KEY_KP_0;
|
|
||||||
_glfw.wl.keycodes[KEY_KP1] = GLFW_KEY_KP_1;
|
|
||||||
_glfw.wl.keycodes[KEY_KP2] = GLFW_KEY_KP_2;
|
|
||||||
_glfw.wl.keycodes[KEY_KP3] = GLFW_KEY_KP_3;
|
|
||||||
_glfw.wl.keycodes[KEY_KP4] = GLFW_KEY_KP_4;
|
|
||||||
_glfw.wl.keycodes[KEY_KP5] = GLFW_KEY_KP_5;
|
|
||||||
_glfw.wl.keycodes[KEY_KP6] = GLFW_KEY_KP_6;
|
|
||||||
_glfw.wl.keycodes[KEY_KP7] = GLFW_KEY_KP_7;
|
|
||||||
_glfw.wl.keycodes[KEY_KP8] = GLFW_KEY_KP_8;
|
|
||||||
_glfw.wl.keycodes[KEY_KP9] = GLFW_KEY_KP_9;
|
|
||||||
_glfw.wl.keycodes[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
|
|
||||||
_glfw.wl.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
|
|
||||||
_glfw.wl.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
|
|
||||||
|
|
||||||
for (scancode = 0; scancode < 256; scancode++)
|
|
||||||
{
|
|
||||||
if (_glfw.wl.keycodes[scancode] > 0)
|
|
||||||
_glfw.wl.scancodes[_glfw.wl.keycodes[scancode]] = scancode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
@ -971,53 +712,7 @@ int _glfwPlatformInit(void)
|
|||||||
_glfw.wl.egl.window_resize = (PFN_wl_egl_window_resize)
|
_glfw.wl.egl.window_resize = (PFN_wl_egl_window_resize)
|
||||||
_glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_resize");
|
_glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_resize");
|
||||||
|
|
||||||
_glfw.wl.xkb.handle = _glfw_dlopen("libxkbcommon.so.0");
|
load_glfw_xkb();
|
||||||
if (!_glfw.wl.xkb.handle)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Wayland: Failed to open libxkbcommon");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.wl.xkb.context_new = (PFN_xkb_context_new)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_new");
|
|
||||||
_glfw.wl.xkb.context_unref = (PFN_xkb_context_unref)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_unref");
|
|
||||||
_glfw.wl.xkb.keymap_new_from_string = (PFN_xkb_keymap_new_from_string)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_new_from_string");
|
|
||||||
_glfw.wl.xkb.keymap_unref = (PFN_xkb_keymap_unref)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_unref");
|
|
||||||
_glfw.wl.xkb.keymap_mod_get_index = (PFN_xkb_keymap_mod_get_index)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");
|
|
||||||
_glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats");
|
|
||||||
_glfw.wl.xkb.state_new = (PFN_xkb_state_new)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_new");
|
|
||||||
_glfw.wl.xkb.state_unref = (PFN_xkb_state_unref)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_unref");
|
|
||||||
_glfw.wl.xkb.state_key_get_syms = (PFN_xkb_state_key_get_syms)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_syms");
|
|
||||||
_glfw.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask");
|
|
||||||
_glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods");
|
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
_glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale");
|
|
||||||
_glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_unref");
|
|
||||||
_glfw.wl.xkb.compose_state_new = (PFN_xkb_compose_state_new)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_new");
|
|
||||||
_glfw.wl.xkb.compose_state_unref = (PFN_xkb_compose_state_unref)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_unref");
|
|
||||||
_glfw.wl.xkb.compose_state_feed = (PFN_xkb_compose_state_feed)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_feed");
|
|
||||||
_glfw.wl.xkb.compose_state_get_status = (PFN_xkb_compose_state_get_status)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status");
|
|
||||||
_glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
_glfw.wl.display = wl_display_connect(NULL);
|
_glfw.wl.display = wl_display_connect(NULL);
|
||||||
if (!_glfw.wl.display)
|
if (!_glfw.wl.display)
|
||||||
@ -1030,15 +725,7 @@ int _glfwPlatformInit(void)
|
|||||||
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
|
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
|
||||||
wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL);
|
wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL);
|
||||||
|
|
||||||
createKeyTables();
|
create_glfw_xkb_context();
|
||||||
|
|
||||||
_glfw.wl.xkb.context = xkb_context_new(0);
|
|
||||||
if (!_glfw.wl.xkb.context)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Wayland: Failed to initialize xkb context");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sync so we got all registry objects
|
// Sync so we got all registry objects
|
||||||
wl_display_roundtrip(_glfw.wl.display);
|
wl_display_roundtrip(_glfw.wl.display);
|
||||||
@ -1053,10 +740,6 @@ int _glfwPlatformInit(void)
|
|||||||
|
|
||||||
_glfwInitTimerPOSIX();
|
_glfwInitTimerPOSIX();
|
||||||
|
|
||||||
_glfw.wl.timerfd = -1;
|
|
||||||
if (_glfw.wl.seatVersion >= 4)
|
|
||||||
_glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
|
|
||||||
|
|
||||||
if (_glfw.wl.pointer && _glfw.wl.shm)
|
if (_glfw.wl.pointer && _glfw.wl.shm)
|
||||||
{
|
{
|
||||||
_glfw.wl.cursorTheme = wl_cursor_theme_load(NULL, 32, _glfw.wl.shm);
|
_glfw.wl.cursorTheme = wl_cursor_theme_load(NULL, 32, _glfw.wl.shm);
|
||||||
@ -1085,21 +768,7 @@ void _glfwPlatformTerminate(void)
|
|||||||
_glfw.wl.egl.handle = NULL;
|
_glfw.wl.egl.handle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
release_glfw_xkb();
|
||||||
if (_glfw.wl.xkb.composeState)
|
|
||||||
xkb_compose_state_unref(_glfw.wl.xkb.composeState);
|
|
||||||
#endif
|
|
||||||
if (_glfw.wl.xkb.keymap)
|
|
||||||
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
|
||||||
if (_glfw.wl.xkb.state)
|
|
||||||
xkb_state_unref(_glfw.wl.xkb.state);
|
|
||||||
if (_glfw.wl.xkb.context)
|
|
||||||
xkb_context_unref(_glfw.wl.xkb.context);
|
|
||||||
if (_glfw.wl.xkb.handle)
|
|
||||||
{
|
|
||||||
_glfw_dlclose(_glfw.wl.xkb.handle);
|
|
||||||
_glfw.wl.xkb.handle = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfw.wl.cursorTheme)
|
if (_glfw.wl.cursorTheme)
|
||||||
wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
|
wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
|
||||||
@ -1158,4 +827,3 @@ const char* _glfwPlatformGetVersionString(void)
|
|||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
101
glfw/wl_platform.h
vendored
101
glfw/wl_platform.h
vendored
@ -25,10 +25,6 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
#include <xkbcommon/xkbcommon-compose.h>
|
|
||||||
#endif
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
|
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
|
||||||
@ -52,6 +48,8 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
|
|||||||
#else
|
#else
|
||||||
#include "null_joystick.h"
|
#include "null_joystick.h"
|
||||||
#endif
|
#endif
|
||||||
|
#define GLFW_XKB_GLOBAL_NAME _glfw.wl.xkb
|
||||||
|
#include "xkb_glfw.h"
|
||||||
#include "xkb_unicode.h"
|
#include "xkb_unicode.h"
|
||||||
#include "egl_context.h"
|
#include "egl_context.h"
|
||||||
#include "osmesa_context.h"
|
#include "osmesa_context.h"
|
||||||
@ -105,46 +103,6 @@ typedef void (* PFN_wl_egl_window_resize)(struct wl_egl_window*, int, int, int,
|
|||||||
#define wl_egl_window_destroy _glfw.wl.egl.window_destroy
|
#define wl_egl_window_destroy _glfw.wl.egl.window_destroy
|
||||||
#define wl_egl_window_resize _glfw.wl.egl.window_resize
|
#define wl_egl_window_resize _glfw.wl.egl.window_resize
|
||||||
|
|
||||||
typedef struct xkb_context* (* PFN_xkb_context_new)(enum xkb_context_flags);
|
|
||||||
typedef void (* PFN_xkb_context_unref)(struct xkb_context*);
|
|
||||||
typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context*, const char*, enum xkb_keymap_format, enum xkb_keymap_compile_flags);
|
|
||||||
typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*);
|
|
||||||
typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*);
|
|
||||||
typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t);
|
|
||||||
typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
|
|
||||||
typedef void (* PFN_xkb_state_unref)(struct xkb_state*);
|
|
||||||
typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
|
|
||||||
typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
|
|
||||||
typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component);
|
|
||||||
#define xkb_context_new _glfw.wl.xkb.context_new
|
|
||||||
#define xkb_context_unref _glfw.wl.xkb.context_unref
|
|
||||||
#define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string
|
|
||||||
#define xkb_keymap_unref _glfw.wl.xkb.keymap_unref
|
|
||||||
#define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index
|
|
||||||
#define xkb_keymap_key_repeats _glfw.wl.xkb.keymap_key_repeats
|
|
||||||
#define xkb_state_new _glfw.wl.xkb.state_new
|
|
||||||
#define xkb_state_unref _glfw.wl.xkb.state_unref
|
|
||||||
#define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms
|
|
||||||
#define xkb_state_update_mask _glfw.wl.xkb.state_update_mask
|
|
||||||
#define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods
|
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags);
|
|
||||||
typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*);
|
|
||||||
typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags);
|
|
||||||
typedef void (* PFN_xkb_compose_state_unref)(struct xkb_compose_state*);
|
|
||||||
typedef enum xkb_compose_feed_result (* PFN_xkb_compose_state_feed)(struct xkb_compose_state*, xkb_keysym_t);
|
|
||||||
typedef enum xkb_compose_status (* PFN_xkb_compose_state_get_status)(struct xkb_compose_state*);
|
|
||||||
typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_state*);
|
|
||||||
#define xkb_compose_table_new_from_locale _glfw.wl.xkb.compose_table_new_from_locale
|
|
||||||
#define xkb_compose_table_unref _glfw.wl.xkb.compose_table_unref
|
|
||||||
#define xkb_compose_state_new _glfw.wl.xkb.compose_state_new
|
|
||||||
#define xkb_compose_state_unref _glfw.wl.xkb.compose_state_unref
|
|
||||||
#define xkb_compose_state_feed _glfw.wl.xkb.compose_state_feed
|
|
||||||
#define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status
|
|
||||||
#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define _GLFW_DECORATION_WIDTH 4
|
#define _GLFW_DECORATION_WIDTH 4
|
||||||
#define _GLFW_DECORATION_TOP 24
|
#define _GLFW_DECORATION_TOP 24
|
||||||
#define _GLFW_DECORATION_VERTICAL (_GLFW_DECORATION_TOP + _GLFW_DECORATION_WIDTH)
|
#define _GLFW_DECORATION_VERTICAL (_GLFW_DECORATION_TOP + _GLFW_DECORATION_WIDTH)
|
||||||
@ -245,52 +203,16 @@ typedef struct _GLFWlibraryWayland
|
|||||||
|
|
||||||
int32_t keyboardRepeatRate;
|
int32_t keyboardRepeatRate;
|
||||||
int32_t keyboardRepeatDelay;
|
int32_t keyboardRepeatDelay;
|
||||||
int keyboardLastKey;
|
|
||||||
int keyboardLastScancode;
|
|
||||||
int timerfd;
|
|
||||||
short int keycodes[256];
|
|
||||||
short int scancodes[GLFW_KEY_LAST + 1];
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
void* handle;
|
long codepoint;
|
||||||
struct xkb_context* context;
|
int plain;
|
||||||
struct xkb_keymap* keymap;
|
int glfwKeyCode;
|
||||||
struct xkb_state* state;
|
int scancode;
|
||||||
|
GLFWbool isFirstRepeat;
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
double nextRepeatAt;
|
||||||
struct xkb_compose_state* composeState;
|
_GLFWwindow* keyboardFocus;
|
||||||
#endif
|
} keyRepeatInfo;
|
||||||
|
_GLFWXKBData xkb;
|
||||||
xkb_mod_mask_t controlMask;
|
|
||||||
xkb_mod_mask_t altMask;
|
|
||||||
xkb_mod_mask_t shiftMask;
|
|
||||||
xkb_mod_mask_t superMask;
|
|
||||||
xkb_mod_mask_t capsLockMask;
|
|
||||||
xkb_mod_mask_t numLockMask;
|
|
||||||
unsigned int modifiers;
|
|
||||||
|
|
||||||
PFN_xkb_context_new context_new;
|
|
||||||
PFN_xkb_context_unref context_unref;
|
|
||||||
PFN_xkb_keymap_new_from_string keymap_new_from_string;
|
|
||||||
PFN_xkb_keymap_unref keymap_unref;
|
|
||||||
PFN_xkb_keymap_mod_get_index keymap_mod_get_index;
|
|
||||||
PFN_xkb_keymap_key_repeats keymap_key_repeats;
|
|
||||||
PFN_xkb_state_new state_new;
|
|
||||||
PFN_xkb_state_unref state_unref;
|
|
||||||
PFN_xkb_state_key_get_syms state_key_get_syms;
|
|
||||||
PFN_xkb_state_update_mask state_update_mask;
|
|
||||||
PFN_xkb_state_serialize_mods state_serialize_mods;
|
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale;
|
|
||||||
PFN_xkb_compose_table_unref compose_table_unref;
|
|
||||||
PFN_xkb_compose_state_new compose_state_new;
|
|
||||||
PFN_xkb_compose_state_unref compose_state_unref;
|
|
||||||
PFN_xkb_compose_state_feed compose_state_feed;
|
|
||||||
PFN_xkb_compose_state_get_status compose_state_get_status;
|
|
||||||
PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym;
|
|
||||||
#endif
|
|
||||||
} xkb;
|
|
||||||
|
|
||||||
_GLFWwindow* pointerFocus;
|
_GLFWwindow* pointerFocus;
|
||||||
_GLFWwindow* keyboardFocus;
|
_GLFWwindow* keyboardFocus;
|
||||||
@ -340,4 +262,3 @@ typedef struct _GLFWcursorWayland
|
|||||||
|
|
||||||
|
|
||||||
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
|
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
|
||||||
|
|
||||||
|
|||||||
53
glfw/wl_window.c
vendored
53
glfw/wl_window.c
vendored
@ -35,7 +35,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/timerfd.h>
|
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
|
||||||
|
|
||||||
@ -690,16 +689,35 @@ static GLFWbool createXdgSurface(_GLFWwindow* window)
|
|||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dispatchPendingKeyRepeats() {
|
||||||
|
if (_glfw.wl.keyRepeatInfo.nextRepeatAt <= 0 || _glfw.wl.keyRepeatInfo.keyboardFocus != _glfw.wl.keyboardFocus || _glfw.wl.keyboardRepeatRate == 0) return;
|
||||||
|
double now = glfwGetTime();
|
||||||
|
while (_glfw.wl.keyRepeatInfo.nextRepeatAt <= now) {
|
||||||
|
const int mods = _glfw.wl.xkb.modifiers;
|
||||||
|
_glfwInputKey(_glfw.wl.keyRepeatInfo.keyboardFocus, _glfw.wl.keyRepeatInfo.glfwKeyCode, _glfw.wl.keyRepeatInfo.scancode, GLFW_REPEAT, mods);
|
||||||
|
if (_glfw.wl.keyRepeatInfo.codepoint > -1) _glfwInputChar(_glfw.wl.keyRepeatInfo.keyboardFocus, _glfw.wl.keyRepeatInfo.codepoint, mods, _glfw.wl.keyRepeatInfo.plain);
|
||||||
|
now = glfwGetTime();
|
||||||
|
_glfw.wl.keyRepeatInfo.nextRepeatAt = now + (1.0 / _glfw.wl.keyboardRepeatRate);
|
||||||
|
_glfw.wl.keyRepeatInfo.isFirstRepeat = GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
adjustTimeoutForKeyRepeat(int timeout) {
|
||||||
|
if (_glfw.wl.keyRepeatInfo.nextRepeatAt <= 0 || _glfw.wl.keyRepeatInfo.keyboardFocus != _glfw.wl.keyboardFocus || _glfw.wl.keyboardRepeatRate == 0) return timeout;
|
||||||
|
double now = glfwGetTime();
|
||||||
|
if (timeout < 0 || now + timeout / 1000. > _glfw.wl.keyRepeatInfo.nextRepeatAt) {
|
||||||
|
timeout = _glfw.wl.keyRepeatInfo.nextRepeatAt <= now ? 0 : ( (_glfw.wl.keyRepeatInfo.nextRepeatAt - now) * 1000 + 1 );
|
||||||
|
}
|
||||||
|
return timeout;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handleEvents(int timeout)
|
handleEvents(int timeout)
|
||||||
{
|
{
|
||||||
struct wl_display* display = _glfw.wl.display;
|
struct wl_display* display = _glfw.wl.display;
|
||||||
struct pollfd fds[] = {
|
struct pollfd pfd = { wl_display_get_fd(display), POLLIN };
|
||||||
{ wl_display_get_fd(display), POLLIN },
|
|
||||||
{ _glfw.wl.timerfd, POLLIN },
|
|
||||||
};
|
|
||||||
ssize_t read_ret;
|
|
||||||
uint64_t repeats, i;
|
|
||||||
|
|
||||||
while (wl_display_prepare_read(display) != 0)
|
while (wl_display_prepare_read(display) != 0)
|
||||||
wl_display_dispatch_pending(display);
|
wl_display_dispatch_pending(display);
|
||||||
@ -719,9 +737,12 @@ handleEvents(int timeout)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (poll(fds, 2, timeout) > 0)
|
dispatchPendingKeyRepeats();
|
||||||
|
timeout = adjustTimeoutForKeyRepeat(timeout);
|
||||||
|
|
||||||
|
if (poll(&pfd, 1, timeout) > 0)
|
||||||
{
|
{
|
||||||
if (fds[0].revents & POLLIN)
|
if (pfd.revents & POLLIN)
|
||||||
{
|
{
|
||||||
wl_display_read_events(display);
|
wl_display_read_events(display);
|
||||||
wl_display_dispatch_pending(display);
|
wl_display_dispatch_pending(display);
|
||||||
@ -731,22 +752,12 @@ handleEvents(int timeout)
|
|||||||
wl_display_cancel_read(display);
|
wl_display_cancel_read(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fds[1].revents & POLLIN)
|
|
||||||
{
|
|
||||||
read_ret = read(_glfw.wl.timerfd, &repeats, sizeof(repeats));
|
|
||||||
if (read_ret != 8)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < repeats; ++i)
|
|
||||||
_glfwInputKey(_glfw.wl.keyboardFocus, _glfw.wl.keyboardLastKey,
|
|
||||||
_glfw.wl.keyboardLastScancode, GLFW_REPEAT,
|
|
||||||
_glfw.wl.xkb.modifiers);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wl_display_cancel_read(display);
|
wl_display_cancel_read(display);
|
||||||
}
|
}
|
||||||
|
dispatchPendingKeyRepeats();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translates a GLFW standard cursor to a theme cursor name
|
// Translates a GLFW standard cursor to a theme cursor name
|
||||||
@ -1240,7 +1251,7 @@ const char* _glfwPlatformGetScancodeName(int scancode)
|
|||||||
|
|
||||||
int _glfwPlatformGetKeyScancode(int key)
|
int _glfwPlatformGetKeyScancode(int key)
|
||||||
{
|
{
|
||||||
return _glfw.wl.scancodes[key];
|
return _glfw.wl.xkb.scancodes[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||||
|
|||||||
374
glfw/xkb_glfw.h
vendored
Normal file
374
glfw/xkb_glfw.h
vendored
Normal file
@ -0,0 +1,374 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 XKB - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2014 Kovid Goyal <kovid@kovidgoyal.net>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#include <xkbcommon/xkbcommon-compose.h>
|
||||||
|
|
||||||
|
typedef struct xkb_context* (* PFN_xkb_context_new)(enum xkb_context_flags);
|
||||||
|
typedef void (* PFN_xkb_context_unref)(struct xkb_context*);
|
||||||
|
typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context*, const char*, enum xkb_keymap_format, enum xkb_keymap_compile_flags);
|
||||||
|
typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*);
|
||||||
|
typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*);
|
||||||
|
typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t);
|
||||||
|
typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
|
||||||
|
typedef void (* PFN_xkb_state_unref)(struct xkb_state*);
|
||||||
|
typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
|
||||||
|
typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
|
||||||
|
typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component);
|
||||||
|
|
||||||
|
#define xkb_context_new GLFW_XKB_GLOBAL_NAME.context_new
|
||||||
|
#define xkb_context_unref GLFW_XKB_GLOBAL_NAME.context_unref
|
||||||
|
#define xkb_keymap_new_from_string GLFW_XKB_GLOBAL_NAME.keymap_new_from_string
|
||||||
|
#define xkb_keymap_unref GLFW_XKB_GLOBAL_NAME.keymap_unref
|
||||||
|
#define xkb_keymap_mod_get_index GLFW_XKB_GLOBAL_NAME.keymap_mod_get_index
|
||||||
|
#define xkb_keymap_key_repeats GLFW_XKB_GLOBAL_NAME.keymap_key_repeats
|
||||||
|
#define xkb_state_new GLFW_XKB_GLOBAL_NAME.state_new
|
||||||
|
#define xkb_state_unref GLFW_XKB_GLOBAL_NAME.state_unref
|
||||||
|
#define xkb_state_key_get_syms GLFW_XKB_GLOBAL_NAME.state_key_get_syms
|
||||||
|
#define xkb_state_update_mask GLFW_XKB_GLOBAL_NAME.state_update_mask
|
||||||
|
#define xkb_state_serialize_mods GLFW_XKB_GLOBAL_NAME.state_serialize_mods
|
||||||
|
|
||||||
|
typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags);
|
||||||
|
typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*);
|
||||||
|
typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags);
|
||||||
|
typedef void (* PFN_xkb_compose_state_unref)(struct xkb_compose_state*);
|
||||||
|
typedef enum xkb_compose_feed_result (* PFN_xkb_compose_state_feed)(struct xkb_compose_state*, xkb_keysym_t);
|
||||||
|
typedef enum xkb_compose_status (* PFN_xkb_compose_state_get_status)(struct xkb_compose_state*);
|
||||||
|
typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_state*);
|
||||||
|
|
||||||
|
#define xkb_compose_table_new_from_locale GLFW_XKB_GLOBAL_NAME.compose_table_new_from_locale
|
||||||
|
#define xkb_compose_table_unref GLFW_XKB_GLOBAL_NAME.compose_table_unref
|
||||||
|
#define xkb_compose_state_new GLFW_XKB_GLOBAL_NAME.compose_state_new
|
||||||
|
#define xkb_compose_state_unref GLFW_XKB_GLOBAL_NAME.compose_state_unref
|
||||||
|
#define xkb_compose_state_feed GLFW_XKB_GLOBAL_NAME.compose_state_feed
|
||||||
|
#define xkb_compose_state_get_status GLFW_XKB_GLOBAL_NAME.compose_state_get_status
|
||||||
|
#define xkb_compose_state_get_one_sym GLFW_XKB_GLOBAL_NAME.compose_state_get_one_sym
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void* handle;
|
||||||
|
struct xkb_context* context;
|
||||||
|
struct xkb_keymap* keymap;
|
||||||
|
struct xkb_state* state;
|
||||||
|
struct xkb_compose_state* composeState;
|
||||||
|
short int keycodes[256];
|
||||||
|
short int scancodes[GLFW_KEY_LAST + 1];
|
||||||
|
|
||||||
|
xkb_mod_mask_t controlMask;
|
||||||
|
xkb_mod_mask_t altMask;
|
||||||
|
xkb_mod_mask_t shiftMask;
|
||||||
|
xkb_mod_mask_t superMask;
|
||||||
|
xkb_mod_mask_t capsLockMask;
|
||||||
|
xkb_mod_mask_t numLockMask;
|
||||||
|
unsigned int modifiers;
|
||||||
|
|
||||||
|
PFN_xkb_context_new context_new;
|
||||||
|
PFN_xkb_context_unref context_unref;
|
||||||
|
PFN_xkb_keymap_new_from_string keymap_new_from_string;
|
||||||
|
PFN_xkb_keymap_unref keymap_unref;
|
||||||
|
PFN_xkb_keymap_mod_get_index keymap_mod_get_index;
|
||||||
|
PFN_xkb_keymap_key_repeats keymap_key_repeats;
|
||||||
|
PFN_xkb_state_new state_new;
|
||||||
|
PFN_xkb_state_unref state_unref;
|
||||||
|
PFN_xkb_state_key_get_syms state_key_get_syms;
|
||||||
|
PFN_xkb_state_update_mask state_update_mask;
|
||||||
|
PFN_xkb_state_serialize_mods state_serialize_mods;
|
||||||
|
|
||||||
|
PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale;
|
||||||
|
PFN_xkb_compose_table_unref compose_table_unref;
|
||||||
|
PFN_xkb_compose_state_new compose_state_new;
|
||||||
|
PFN_xkb_compose_state_unref compose_state_unref;
|
||||||
|
PFN_xkb_compose_state_feed compose_state_feed;
|
||||||
|
PFN_xkb_compose_state_get_status compose_state_get_status;
|
||||||
|
PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym;
|
||||||
|
} _GLFWXKBData;
|
||||||
|
|
||||||
|
#define bind_xkb_sym(name) GLFW_XKB_GLOBAL_NAME.name = (PFN_xkb_##name) _glfw_dlsym(GLFW_XKB_GLOBAL_NAME.handle, "xkb_" #name)
|
||||||
|
#define load_glfw_xkb() {\
|
||||||
|
GLFW_XKB_GLOBAL_NAME.handle = _glfw_dlopen("libxkbcommon.so.0"); \
|
||||||
|
if (!GLFW_XKB_GLOBAL_NAME.handle) \
|
||||||
|
{ \
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, \
|
||||||
|
"Failed to open libxkbcommon"); \
|
||||||
|
return GLFW_FALSE; \
|
||||||
|
} \
|
||||||
|
bind_xkb_sym(context_new); \
|
||||||
|
bind_xkb_sym(context_unref); \
|
||||||
|
bind_xkb_sym(keymap_new_from_string); \
|
||||||
|
bind_xkb_sym(keymap_unref); \
|
||||||
|
bind_xkb_sym(keymap_mod_get_index); \
|
||||||
|
bind_xkb_sym(keymap_key_repeats); \
|
||||||
|
bind_xkb_sym(state_new); \
|
||||||
|
bind_xkb_sym(state_unref); \
|
||||||
|
bind_xkb_sym(state_key_get_syms); \
|
||||||
|
bind_xkb_sym(state_update_mask); \
|
||||||
|
bind_xkb_sym(state_serialize_mods); \
|
||||||
|
bind_xkb_sym(compose_table_new_from_locale); \
|
||||||
|
bind_xkb_sym(compose_table_unref); \
|
||||||
|
bind_xkb_sym(compose_state_new); \
|
||||||
|
bind_xkb_sym(compose_state_unref); \
|
||||||
|
bind_xkb_sym(compose_state_feed); \
|
||||||
|
bind_xkb_sym(compose_state_get_status); \
|
||||||
|
bind_xkb_sym(compose_state_get_one_sym); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define release_glfw_xkb() {\
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.composeState) { \
|
||||||
|
xkb_compose_state_unref(GLFW_XKB_GLOBAL_NAME.composeState); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.composeState = NULL; \
|
||||||
|
} \
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.keymap) { \
|
||||||
|
xkb_keymap_unref(GLFW_XKB_GLOBAL_NAME.keymap); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keymap = NULL; \
|
||||||
|
} \
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.state) { \
|
||||||
|
xkb_state_unref(GLFW_XKB_GLOBAL_NAME.state); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.state = NULL; \
|
||||||
|
} \
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.context) { \
|
||||||
|
xkb_context_unref(GLFW_XKB_GLOBAL_NAME.context); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.context = NULL; \
|
||||||
|
} \
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.handle) { \
|
||||||
|
_glfw_dlclose(GLFW_XKB_GLOBAL_NAME.handle); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.handle = NULL; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define create_glfw_xkb_context() {\
|
||||||
|
GLFW_XKB_GLOBAL_NAME.context = xkb_context_new(0); \
|
||||||
|
if (!GLFW_XKB_GLOBAL_NAME.context) \
|
||||||
|
{ \
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, \
|
||||||
|
"Failed to initialize xkb context"); \
|
||||||
|
return GLFW_FALSE; \
|
||||||
|
} \
|
||||||
|
int scancode; \
|
||||||
|
memset(GLFW_XKB_GLOBAL_NAME.keycodes, -1, sizeof(GLFW_XKB_GLOBAL_NAME.keycodes)); \
|
||||||
|
memset(GLFW_XKB_GLOBAL_NAME.scancodes, -1, sizeof(GLFW_XKB_GLOBAL_NAME.scancodes)); \
|
||||||
|
\
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_1] = GLFW_KEY_1; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_2] = GLFW_KEY_2; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_3] = GLFW_KEY_3; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_4] = GLFW_KEY_4; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_5] = GLFW_KEY_5; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_6] = GLFW_KEY_6; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_7] = GLFW_KEY_7; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_8] = GLFW_KEY_8; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_9] = GLFW_KEY_9; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_0] = GLFW_KEY_0; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_SPACE] = GLFW_KEY_SPACE; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_MINUS] = GLFW_KEY_MINUS; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_EQUAL] = GLFW_KEY_EQUAL; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_Q] = GLFW_KEY_Q; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_W] = GLFW_KEY_W; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_E] = GLFW_KEY_E; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_R] = GLFW_KEY_R; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_T] = GLFW_KEY_T; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_Y] = GLFW_KEY_Y; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_U] = GLFW_KEY_U; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_I] = GLFW_KEY_I; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_O] = GLFW_KEY_O; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_P] = GLFW_KEY_P; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_A] = GLFW_KEY_A; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_S] = GLFW_KEY_S; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_D] = GLFW_KEY_D; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F] = GLFW_KEY_F; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_G] = GLFW_KEY_G; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_H] = GLFW_KEY_H; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_J] = GLFW_KEY_J; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_K] = GLFW_KEY_K; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_L] = GLFW_KEY_L; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_Z] = GLFW_KEY_Z; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_X] = GLFW_KEY_X; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_C] = GLFW_KEY_C; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_V] = GLFW_KEY_V; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_B] = GLFW_KEY_B; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_N] = GLFW_KEY_N; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_M] = GLFW_KEY_M; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_COMMA] = GLFW_KEY_COMMA; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_DOT] = GLFW_KEY_PERIOD; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_SLASH] = GLFW_KEY_SLASH; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_ESC] = GLFW_KEY_ESCAPE; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_TAB] = GLFW_KEY_TAB; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_MENU] = GLFW_KEY_MENU; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_PAUSE] = GLFW_KEY_PAUSE; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_DELETE] = GLFW_KEY_DELETE; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_ENTER] = GLFW_KEY_ENTER; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_HOME] = GLFW_KEY_HOME; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_END] = GLFW_KEY_END; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_PAGEUP] = GLFW_KEY_PAGE_UP; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_INSERT] = GLFW_KEY_INSERT; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_LEFT] = GLFW_KEY_LEFT; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_RIGHT] = GLFW_KEY_RIGHT; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_DOWN] = GLFW_KEY_DOWN; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_UP] = GLFW_KEY_UP; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F1] = GLFW_KEY_F1; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F2] = GLFW_KEY_F2; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F3] = GLFW_KEY_F3; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F4] = GLFW_KEY_F4; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F5] = GLFW_KEY_F5; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F6] = GLFW_KEY_F6; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F7] = GLFW_KEY_F7; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F8] = GLFW_KEY_F8; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F9] = GLFW_KEY_F9; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F10] = GLFW_KEY_F10; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F11] = GLFW_KEY_F11; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F12] = GLFW_KEY_F12; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F13] = GLFW_KEY_F13; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F14] = GLFW_KEY_F14; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F15] = GLFW_KEY_F15; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F16] = GLFW_KEY_F16; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F17] = GLFW_KEY_F17; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F18] = GLFW_KEY_F18; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F19] = GLFW_KEY_F19; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F20] = GLFW_KEY_F20; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F21] = GLFW_KEY_F21; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F22] = GLFW_KEY_F22; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F23] = GLFW_KEY_F23; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F24] = GLFW_KEY_F24; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP0] = GLFW_KEY_KP_0; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP1] = GLFW_KEY_KP_1; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP2] = GLFW_KEY_KP_2; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP3] = GLFW_KEY_KP_3; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP4] = GLFW_KEY_KP_4; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP5] = GLFW_KEY_KP_5; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP6] = GLFW_KEY_KP_6; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP7] = GLFW_KEY_KP_7; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP8] = GLFW_KEY_KP_8; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP9] = GLFW_KEY_KP_9; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER; \
|
||||||
|
\
|
||||||
|
for (scancode = 0; scancode < 256; scancode++) \
|
||||||
|
{ \
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.keycodes[scancode] > 0) \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.scancodes[GLFW_XKB_GLOBAL_NAME.keycodes[scancode]] = scancode; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define xkb_glfw_compile_keymap(map_str) { \
|
||||||
|
const char* locale = NULL; \
|
||||||
|
struct xkb_state* state = NULL; \
|
||||||
|
struct xkb_keymap* keymap = NULL; \
|
||||||
|
struct xkb_compose_table* compose_table = NULL; \
|
||||||
|
struct xkb_compose_state* compose_state = NULL; \
|
||||||
|
\
|
||||||
|
keymap = xkb_keymap_new_from_string(GLFW_XKB_GLOBAL_NAME.context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0); \
|
||||||
|
if (!keymap) _glfwInputError(GLFW_PLATFORM_ERROR, "Failed to compile XKB keymap"); \
|
||||||
|
else { \
|
||||||
|
state = xkb_state_new(keymap); \
|
||||||
|
if (!state) { \
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to create XKB state"); \
|
||||||
|
xkb_keymap_unref(keymap); keymap = NULL; \
|
||||||
|
} else { \
|
||||||
|
/* Look up the preferred locale, falling back to "C" as default. */ \
|
||||||
|
locale = getenv("LC_ALL"); \
|
||||||
|
if (!locale) locale = getenv("LC_CTYPE"); \
|
||||||
|
if (!locale) locale = getenv("LANG"); \
|
||||||
|
if (!locale) locale = "C"; \
|
||||||
|
compose_table = xkb_compose_table_new_from_locale(GLFW_XKB_GLOBAL_NAME.context, locale, XKB_COMPOSE_COMPILE_NO_FLAGS); \
|
||||||
|
if (!compose_table) { \
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to create XKB compose table"); \
|
||||||
|
xkb_keymap_unref(keymap); keymap = NULL; \
|
||||||
|
xkb_state_unref(state); state = NULL; \
|
||||||
|
} else { \
|
||||||
|
compose_state = xkb_compose_state_new(compose_table, XKB_COMPOSE_STATE_NO_FLAGS); \
|
||||||
|
xkb_compose_table_unref(compose_table); compose_table = NULL; \
|
||||||
|
if (!compose_state) { \
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to create XKB compose state"); \
|
||||||
|
xkb_keymap_unref(keymap); keymap = NULL; \
|
||||||
|
xkb_state_unref(state); state = NULL; \
|
||||||
|
}\
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if (keymap && state && compose_state) { \
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.composeState) xkb_compose_state_unref(GLFW_XKB_GLOBAL_NAME.composeState); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.composeState = compose_state; \
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.keymap) xkb_keymap_unref(GLFW_XKB_GLOBAL_NAME.keymap); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keymap = keymap; \
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.state) xkb_state_unref(GLFW_XKB_GLOBAL_NAME.state); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.state = state; \
|
||||||
|
}\
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.keymap) { \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.controlMask = 1 << xkb_keymap_mod_get_index(GLFW_XKB_GLOBAL_NAME.keymap, "Control"); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.altMask = 1 << xkb_keymap_mod_get_index(GLFW_XKB_GLOBAL_NAME.keymap, "Mod1"); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.shiftMask = 1 << xkb_keymap_mod_get_index(GLFW_XKB_GLOBAL_NAME.keymap, "Shift"); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.superMask = 1 << xkb_keymap_mod_get_index(GLFW_XKB_GLOBAL_NAME.keymap, "Mod4"); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.capsLockMask = 1 << xkb_keymap_mod_get_index(GLFW_XKB_GLOBAL_NAME.keymap, "Lock"); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.numLockMask = 1 << xkb_keymap_mod_get_index(GLFW_XKB_GLOBAL_NAME.keymap, "Mod2"); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define xkb_glfw_update_modifiers(depressed, latched, locked) {\
|
||||||
|
xkb_mod_mask_t mask; \
|
||||||
|
unsigned int modifiers = 0; \
|
||||||
|
if (!GLFW_XKB_GLOBAL_NAME.keymap) return; \
|
||||||
|
xkb_state_update_mask(GLFW_XKB_GLOBAL_NAME.state, depressed, latched, locked, 0, 0, group); \
|
||||||
|
mask = xkb_state_serialize_mods(GLFW_XKB_GLOBAL_NAME.state, XKB_STATE_MODS_DEPRESSED | XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_MODS_LATCHED | XKB_STATE_LAYOUT_LATCHED); \
|
||||||
|
if (mask & GLFW_XKB_GLOBAL_NAME.controlMask) modifiers |= GLFW_MOD_CONTROL; \
|
||||||
|
if (mask & GLFW_XKB_GLOBAL_NAME.altMask) modifiers |= GLFW_MOD_ALT; \
|
||||||
|
if (mask & GLFW_XKB_GLOBAL_NAME.shiftMask) modifiers |= GLFW_MOD_SHIFT; \
|
||||||
|
if (mask & GLFW_XKB_GLOBAL_NAME.superMask) modifiers |= GLFW_MOD_SUPER; \
|
||||||
|
if (mask & GLFW_XKB_GLOBAL_NAME.capsLockMask) modifiers |= GLFW_MOD_CAPS_LOCK; \
|
||||||
|
if (mask & GLFW_XKB_GLOBAL_NAME.numLockMask) modifiers |= GLFW_MOD_NUM_LOCK; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.modifiers = modifiers; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define xkb_glfw_to_glfw_key_code(key) \
|
||||||
|
((key < sizeof(GLFW_XKB_GLOBAL_NAME.keycodes) / sizeof(GLFW_XKB_GLOBAL_NAME.keycodes[0])) ? GLFW_XKB_GLOBAL_NAME.keycodes[key] : GLFW_KEY_UNKNOWN)
|
||||||
Loading…
x
Reference in New Issue
Block a user