Linux: Fix release event for the final key in a compose sequence not being reported. Fixes #4285
This commit is contained in:
parent
cdb1138465
commit
bd288bd18f
@ -1250,7 +1250,7 @@ is_ascii_control_char(char x) {
|
|||||||
const bool process_text = !window->ns.textInputFilterCallback || window->ns.textInputFilterCallback(key, mods, keycode, flags) != 1;
|
const bool process_text = !window->ns.textInputFilterCallback || window->ns.textInputFilterCallback(key, mods, keycode, flags) != 1;
|
||||||
_glfw.ns.text[0] = 0;
|
_glfw.ns.text[0] = 0;
|
||||||
if (keycode == 0x33 /* backspace */ || keycode == 0x35 /* escape */) [self unmarkText];
|
if (keycode == 0x33 /* backspace */ || keycode == 0x35 /* escape */) [self unmarkText];
|
||||||
GLFWkeyevent glfw_keyevent = {.key = key, .native_key = keycode, .action = GLFW_PRESS, .mods = mods};
|
GLFWkeyevent glfw_keyevent = {.key = key, .native_key = keycode, .native_key_id = keycode, .action = GLFW_PRESS, .mods = mods};
|
||||||
if (!_glfw.ns.unicodeData) {
|
if (!_glfw.ns.unicodeData) {
|
||||||
// Using the cocoa API for key handling is disabled, as there is no
|
// Using the cocoa API for key handling is disabled, as there is no
|
||||||
// reliable way to handle dead keys using it. Only use it if the
|
// reliable way to handle dead keys using it. Only use it if the
|
||||||
@ -1357,7 +1357,7 @@ is_ascii_control_char(char x) {
|
|||||||
action = GLFW_PRESS;
|
action = GLFW_PRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWkeyevent glfw_keyevent = {.key = key, .native_key = [event keyCode], .action = action, .mods = mods};
|
GLFWkeyevent glfw_keyevent = {.key = key, .native_key = [event keyCode], .native_key_id = [event keyCode], .action = action, .mods = mods};
|
||||||
_glfwInputKeyboard(window, &glfw_keyevent);
|
_glfwInputKeyboard(window, &glfw_keyevent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1367,7 +1367,7 @@ is_ascii_control_char(char x) {
|
|||||||
const uint32_t key = translateKey(keycode, true);
|
const uint32_t key = translateKey(keycode, true);
|
||||||
const int mods = translateFlags([event modifierFlags]);
|
const int mods = translateFlags([event modifierFlags]);
|
||||||
|
|
||||||
GLFWkeyevent glfw_keyevent = {.key = key, .native_key = keycode, .action = GLFW_RELEASE, .mods = mods};
|
GLFWkeyevent glfw_keyevent = {.key = key, .native_key = keycode, .native_key_id = keycode, .action = GLFW_RELEASE, .mods = mods};
|
||||||
add_alternate_keys(&glfw_keyevent, event);
|
add_alternate_keys(&glfw_keyevent, event);
|
||||||
debug_key("\x1b[32mRelease:\x1b[m native_key: 0x%x (%s) glfw_key: 0x%x %s\n",
|
debug_key("\x1b[32mRelease:\x1b[m native_key: 0x%x (%s) glfw_key: 0x%x %s\n",
|
||||||
keycode, safe_name_for_keycode(keycode), key, format_mods(mods));
|
keycode, safe_name_for_keycode(keycode), key, format_mods(mods));
|
||||||
|
|||||||
4
glfw/glfw3.h
vendored
4
glfw/glfw3.h
vendored
@ -1245,6 +1245,10 @@ typedef struct GLFWkeyevent
|
|||||||
// A value of GLFW_IME_PREEDIT_CHANGED means the pre-edit text for the input event has been changed.
|
// A value of GLFW_IME_PREEDIT_CHANGED means the pre-edit text for the input event has been changed.
|
||||||
// A value of GLFW_IME_COMMIT_TEXT means the text should be committed.
|
// A value of GLFW_IME_COMMIT_TEXT means the text should be committed.
|
||||||
GLFWIMEState ime_state;
|
GLFWIMEState ime_state;
|
||||||
|
|
||||||
|
// For internal use only. On Linux it is the actual keycode reported by the windowing system, in contrast
|
||||||
|
// to native_key which can be the result of a compose operation. On macOS it is the same as native_key.
|
||||||
|
uint32_t native_key_id;
|
||||||
} GLFWkeyevent;
|
} GLFWkeyevent;
|
||||||
|
|
||||||
/*! @brief The function pointer type for error callbacks.
|
/*! @brief The function pointer type for error callbacks.
|
||||||
|
|||||||
40
glfw/input.c
vendored
40
glfw/input.c
vendored
@ -274,11 +274,11 @@ static bool parseMapping(_GLFWmapping* mapping, const char* string)
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_key_action(_GLFWwindow *window, uint32_t key, int val, int idx) {
|
set_key_action(_GLFWwindow *window, const GLFWkeyevent *ev, int action, int idx) {
|
||||||
const unsigned sz = arraysz(window->activated_keys);
|
const unsigned sz = arraysz(window->activated_keys);
|
||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
for (unsigned i = 0; i < sz; i++) {
|
for (unsigned i = 0; i < sz; i++) {
|
||||||
if (window->activated_keys[i].key == 0) {
|
if (window->activated_keys[i].native_key_id == 0) {
|
||||||
idx = i;
|
idx = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -286,18 +286,18 @@ set_key_action(_GLFWwindow *window, uint32_t key, int val, int idx) {
|
|||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
idx = sz - 1;
|
idx = sz - 1;
|
||||||
memmove(window->activated_keys, window->activated_keys + 1, sizeof(window->activated_keys[0]) * (sz - 1));
|
memmove(window->activated_keys, window->activated_keys + 1, sizeof(window->activated_keys[0]) * (sz - 1));
|
||||||
window->activated_keys[sz - 1].key = key;
|
window->activated_keys[sz - 1].native_key_id = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (val == GLFW_RELEASE) {
|
if (action == GLFW_RELEASE) {
|
||||||
memset(window->activated_keys + idx, 0, sizeof(window->activated_keys[0]));
|
memset(window->activated_keys + idx, 0, sizeof(window->activated_keys[0]));
|
||||||
if (idx < (int)sz - 1) {
|
if (idx < (int)sz - 1) {
|
||||||
memmove(window->activated_keys + idx, window->activated_keys + idx + 1, sizeof(window->activated_keys[0]) * (sz - 1 - idx));
|
memmove(window->activated_keys + idx, window->activated_keys + idx + 1, sizeof(window->activated_keys[0]) * (sz - 1 - idx));
|
||||||
memset(window->activated_keys + sz - 1, 0, sizeof(window->activated_keys[0]));
|
memset(window->activated_keys + sz - 1, 0, sizeof(window->activated_keys[0]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
window->activated_keys[idx].key = key;
|
window->activated_keys[idx] = *ev;
|
||||||
window->activated_keys[idx].action = val;
|
window->activated_keys[idx].text = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,30 +305,39 @@ set_key_action(_GLFWwindow *window, uint32_t key, int val, int idx) {
|
|||||||
//
|
//
|
||||||
void _glfwInputKeyboard(_GLFWwindow* window, GLFWkeyevent* ev)
|
void _glfwInputKeyboard(_GLFWwindow* window, GLFWkeyevent* ev)
|
||||||
{
|
{
|
||||||
if (ev->key > 0)
|
if (ev->native_key_id > 0)
|
||||||
{
|
{
|
||||||
bool repeated = false;
|
bool repeated = false;
|
||||||
int idx = -1;
|
int idx = -1;
|
||||||
int current_action = GLFW_RELEASE;
|
int current_action = GLFW_RELEASE;
|
||||||
const unsigned sz = arraysz(window->activated_keys);
|
const unsigned sz = arraysz(window->activated_keys);
|
||||||
for (unsigned i = 0; i < sz; i++) {
|
for (unsigned i = 0; i < sz; i++) {
|
||||||
if (window->activated_keys[i].key == ev->key) {
|
if (window->activated_keys[i].native_key_id == ev->native_key_id) {
|
||||||
idx = i;
|
idx = i;
|
||||||
current_action = window->activated_keys[i].action;
|
current_action = window->activated_keys[i].action;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ev->action == GLFW_RELEASE && current_action == GLFW_RELEASE)
|
if (ev->action == GLFW_RELEASE) {
|
||||||
return;
|
if (current_action == GLFW_RELEASE) return;
|
||||||
|
if (idx > -1) {
|
||||||
|
const GLFWkeyevent *press_event = window->activated_keys + idx;
|
||||||
|
if (press_event->action == GLFW_PRESS || press_event->action == GLFW_REPEAT) {
|
||||||
|
// Compose sequences under X11 give a different key value for press and release events
|
||||||
|
// but we want the same key value so override it.
|
||||||
|
ev->native_key = press_event->native_key;
|
||||||
|
ev->key = press_event->key;
|
||||||
|
ev->shifted_key = press_event->shifted_key;
|
||||||
|
ev->alternate_key = press_event->alternate_key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ev->action == GLFW_PRESS && current_action == GLFW_PRESS)
|
if (ev->action == GLFW_PRESS && current_action == GLFW_PRESS)
|
||||||
repeated = true;
|
repeated = true;
|
||||||
|
|
||||||
if (ev->action == GLFW_RELEASE && window->stickyKeys)
|
set_key_action(window, ev, (ev->action == GLFW_RELEASE && window->stickyKeys) ? _GLFW_STICK : ev->action, idx);
|
||||||
set_key_action(window, ev->key, _GLFW_STICK, idx);
|
|
||||||
else
|
|
||||||
set_key_action(window, ev->key, ev->action, idx);
|
|
||||||
|
|
||||||
if (repeated)
|
if (repeated)
|
||||||
ev->action = GLFW_REPEAT;
|
ev->action = GLFW_REPEAT;
|
||||||
@ -823,7 +832,8 @@ GLFWAPI GLFWKeyAction glfwGetKey(GLFWwindow* handle, uint32_t key)
|
|||||||
if (current_action == _GLFW_STICK)
|
if (current_action == _GLFW_STICK)
|
||||||
{
|
{
|
||||||
// Sticky mode: release key now
|
// Sticky mode: release key now
|
||||||
set_key_action(window, key, GLFW_RELEASE, idx);
|
GLFWkeyevent ev = {0};
|
||||||
|
set_key_action(window, &ev, GLFW_RELEASE, idx);
|
||||||
current_action = GLFW_PRESS;
|
current_action = GLFW_PRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
7
glfw/internal.h
vendored
7
glfw/internal.h
vendored
@ -402,11 +402,6 @@ struct _GLFWcontext
|
|||||||
_GLFWcontextOSMesa osmesa;
|
_GLFWcontextOSMesa osmesa;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct GLFWKeyState {
|
|
||||||
uint32_t key;
|
|
||||||
char action;
|
|
||||||
} GLFWKeyState;
|
|
||||||
|
|
||||||
// Window and context structure
|
// Window and context structure
|
||||||
//
|
//
|
||||||
struct _GLFWwindow
|
struct _GLFWwindow
|
||||||
@ -437,7 +432,7 @@ struct _GLFWwindow
|
|||||||
bool lockKeyMods;
|
bool lockKeyMods;
|
||||||
int cursorMode;
|
int cursorMode;
|
||||||
char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1];
|
char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1];
|
||||||
GLFWKeyState activated_keys[16];
|
GLFWkeyevent activated_keys[16];
|
||||||
// Virtual cursor position when cursor is disabled
|
// Virtual cursor position when cursor is disabled
|
||||||
double virtualCursorPosX, virtualCursorPosY;
|
double virtualCursorPosX, virtualCursorPosY;
|
||||||
bool rawMouseMotion;
|
bool rawMouseMotion;
|
||||||
|
|||||||
2
glfw/xkb_glfw.c
vendored
2
glfw/xkb_glfw.c
vendored
@ -866,7 +866,7 @@ glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t
|
|||||||
const xkb_keysym_t *syms, *clean_syms, *default_syms;
|
const xkb_keysym_t *syms, *clean_syms, *default_syms;
|
||||||
xkb_keysym_t xkb_sym, shifted_xkb_sym = XKB_KEY_NoSymbol, alternate_xkb_sym = XKB_KEY_NoSymbol;
|
xkb_keysym_t xkb_sym, shifted_xkb_sym = XKB_KEY_NoSymbol, alternate_xkb_sym = XKB_KEY_NoSymbol;
|
||||||
xkb_keycode_t code_for_sym = xkb_keycode, ibus_keycode = xkb_keycode;
|
xkb_keycode_t code_for_sym = xkb_keycode, ibus_keycode = xkb_keycode;
|
||||||
GLFWkeyevent glfw_ev = {.action = GLFW_PRESS};
|
GLFWkeyevent glfw_ev = {.action = GLFW_PRESS, .native_key_id = xkb_keycode};
|
||||||
#ifdef _GLFW_WAYLAND
|
#ifdef _GLFW_WAYLAND
|
||||||
code_for_sym += 8;
|
code_for_sym += 8;
|
||||||
#else
|
#else
|
||||||
|
|||||||
4
kitty/glfw-wrapper.h
generated
4
kitty/glfw-wrapper.h
generated
@ -983,6 +983,10 @@ typedef struct GLFWkeyevent
|
|||||||
// A value of GLFW_IME_PREEDIT_CHANGED means the pre-edit text for the input event has been changed.
|
// A value of GLFW_IME_PREEDIT_CHANGED means the pre-edit text for the input event has been changed.
|
||||||
// A value of GLFW_IME_COMMIT_TEXT means the text should be committed.
|
// A value of GLFW_IME_COMMIT_TEXT means the text should be committed.
|
||||||
GLFWIMEState ime_state;
|
GLFWIMEState ime_state;
|
||||||
|
|
||||||
|
// For internal use only. On Linux it is the actual keycode reported by the windowing system, in contrast
|
||||||
|
// to native_key which can be the result of a compose operation. On macOS it is the same as native_key.
|
||||||
|
uint32_t native_key_id;
|
||||||
} GLFWkeyevent;
|
} GLFWkeyevent;
|
||||||
|
|
||||||
/*! @brief The function pointer type for error callbacks.
|
/*! @brief The function pointer type for error callbacks.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user