mirror of
https://github.com/glfw/glfw
synced 2026-09-26 16:18:21 +03:00
Implement a solution for Linux/Wayland.
This works by scanning through all levels of a given key, then through all modifier masks that can produce the given level, until we find a mask that matches the one the user requested.
This commit is contained in:
parent
a27b7d32de
commit
2e147c7bbe
3 changed files with 72 additions and 5 deletions
|
|
@ -691,7 +691,13 @@ int _glfwInitWayland(void)
|
|||
_glfw.wl.xkb.keymap_unref = (PFN_xkb_keymap_unref)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_unref");
|
||||
_glfw.wl.xkb.keymap_mod_get_index = (PFN_xkb_keymap_mod_get_index)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");
|
||||
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");
|
||||
_glfw.wl.xkb.keymap_mod_get_mask2 = (PFN_xkb_keymap_mod_get_mask2)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_mask2");
|
||||
_glfw.wl.xkb.keymap_key_get_mods_for_level = (PFN_xkb_keymap_key_get_mods_for_level)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_key_get_mods_for_level");
|
||||
_glfw.wl.xkb.keymap_num_levels_for_key = (PFN_xkb_keymap_num_levels_for_key)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_num_levels_for_key");
|
||||
_glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats");
|
||||
_glfw.wl.xkb.keymap_key_get_syms_by_level = (PFN_xkb_keymap_key_get_syms_by_level)
|
||||
|
|
|
|||
|
|
@ -185,6 +185,9 @@ 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 xkb_mod_mask_t (* PFN_xkb_keymap_mod_get_mask2)(struct xkb_keymap*, const xkb_mod_index_t);
|
||||
typedef xkb_level_index_t (* PFN_xkb_keymap_num_levels_for_key)(struct xkb_keymap*, const xkb_keycode_t, const xkb_layout_index_t);
|
||||
typedef size_t (* PFN_xkb_keymap_key_get_mods_for_level)(struct xkb_keymap*, const xkb_keycode_t, const xkb_layout_index_t, const xkb_level_index_t, xkb_mod_mask_t *, const size_t);
|
||||
typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t);
|
||||
typedef int (* PFN_xkb_keymap_key_get_syms_by_level)(struct xkb_keymap*,xkb_keycode_t,xkb_layout_index_t,xkb_level_index_t,const xkb_keysym_t**);
|
||||
typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
|
||||
|
|
@ -200,6 +203,9 @@ typedef int (* PFN_xkb_keysym_to_utf8)(xkb_keysym_t, char*, size_t);
|
|||
#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_mod_get_mask2 _glfw.wl.xkb.keymap_mod_get_mask2
|
||||
#define xkb_keymap_num_levels_for_key _glfw.wl.xkb.keymap_num_levels_for_key
|
||||
#define xkb_keymap_key_get_mods_for_level _glfw.wl.xkb.keymap_key_get_mods_for_level
|
||||
#define xkb_keymap_key_repeats _glfw.wl.xkb.keymap_key_repeats
|
||||
#define xkb_keymap_key_get_syms_by_level _glfw.wl.xkb.keymap_key_get_syms_by_level
|
||||
#define xkb_state_new _glfw.wl.xkb.state_new
|
||||
|
|
@ -524,8 +530,11 @@ typedef struct _GLFWlibraryWayland
|
|||
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_mod_get_mask2 keymap_mod_get_mask2;
|
||||
PFN_xkb_keymap_key_repeats keymap_key_repeats;
|
||||
PFN_xkb_keymap_key_get_syms_by_level keymap_key_get_syms_by_level;
|
||||
PFN_xkb_keymap_num_levels_for_key keymap_num_levels_for_key;
|
||||
PFN_xkb_keymap_key_get_mods_for_level keymap_key_get_mods_for_level;
|
||||
PFN_xkb_state_new state_new;
|
||||
PFN_xkb_state_unref state_unref;
|
||||
PFN_xkb_state_key_get_syms state_key_get_syms;
|
||||
|
|
|
|||
|
|
@ -2978,6 +2978,28 @@ void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode)
|
|||
_glfwSetCursorWayland(window, window->cursor);
|
||||
}
|
||||
|
||||
// Translates an xkb modifier state mask
|
||||
//
|
||||
static xkb_mod_mask_t translateStateInverse(int mods)
|
||||
{
|
||||
xkb_mod_mask_t mask = 0;
|
||||
|
||||
if (mods & GLFW_MOD_SHIFT)
|
||||
mask |= xkb_keymap_mod_get_mask2(_glfw.wl.xkb.keymap, _glfw.wl.xkb.shiftIndex);
|
||||
if (mods & GLFW_MOD_CONTROL)
|
||||
mask |= xkb_keymap_mod_get_mask2(_glfw.wl.xkb.keymap, _glfw.wl.xkb.controlIndex);
|
||||
if (mods & GLFW_MOD_ALT)
|
||||
mask |= xkb_keymap_mod_get_mask2(_glfw.wl.xkb.keymap, _glfw.wl.xkb.altIndex);
|
||||
if (mods & GLFW_MOD_SUPER)
|
||||
mask |= xkb_keymap_mod_get_mask2(_glfw.wl.xkb.keymap, _glfw.wl.xkb.superIndex);
|
||||
if (mods & GLFW_MOD_CAPS_LOCK)
|
||||
mask |= xkb_keymap_mod_get_mask2(_glfw.wl.xkb.keymap, _glfw.wl.xkb.capsLockIndex);
|
||||
if (mods & GLFW_MOD_NUM_LOCK)
|
||||
mask |= xkb_keymap_mod_get_mask2(_glfw.wl.xkb.keymap, _glfw.wl.xkb.numLockIndex);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
const char* _glfwGetScancodeNameWayland(int scancode, int modifiers)
|
||||
{
|
||||
if (scancode < 0 || scancode > 255)
|
||||
|
|
@ -3002,14 +3024,44 @@ const char* _glfwGetScancodeNameWayland(int scancode, int modifiers)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// FIXME: can't seem to find any way in libxkbcommon to translate an xkb_mod_mask_t into
|
||||
// a xkb_level_index_t . Sigh.
|
||||
int level = (modifiers & GLFW_MOD_SHIFT)? 1 : 0;
|
||||
xkb_level_index_t found_level = 0;
|
||||
if (0 < modifiers)
|
||||
{
|
||||
// Figure out the corresponding level set for the modifier set
|
||||
// that the user requested. This involves a relatively annoying
|
||||
// loop of trying things out. Could cache this information if
|
||||
// lookup speed is of concern.
|
||||
xkb_mod_mask_t mask = translateStateInverse(modifiers);
|
||||
const int num_levels = xkb_keymap_num_levels_for_key(_glfw.wl.xkb.keymap,
|
||||
keycode,
|
||||
layout);
|
||||
xkb_level_index_t level;
|
||||
for (level = 0; level < num_levels && found_level == 0; ++level)
|
||||
{
|
||||
size_t num_masks;
|
||||
xkb_mod_mask_t masks[128];
|
||||
num_masks = xkb_keymap_key_get_mods_for_level(_glfw.wl.xkb.keymap,
|
||||
keycode,
|
||||
layout,
|
||||
level,
|
||||
masks,
|
||||
128);
|
||||
for (int i=0; i < num_masks; ++i)
|
||||
{
|
||||
if ((masks[i] & mask) == mask)
|
||||
{
|
||||
found_level = level;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const xkb_keysym_t* keysyms = NULL;
|
||||
xkb_keymap_key_get_syms_by_level(_glfw.wl.xkb.keymap,
|
||||
keycode,
|
||||
layout,
|
||||
level,
|
||||
found_level,
|
||||
&keysyms);
|
||||
if (keysyms == NULL)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue