mirror of
https://github.com/glfw/glfw.git
synced 2025-01-31 20:30:28 +00:00
Fixed filtering of events duplicated by XIM.
Duplicate events cannot be filtered by the return value of XFilterEvent, as that discards dead key events on some IMs (ibus), nor by its inverse, as that discards all key events on other IMs (?). This solution is based on the workaround in SDL2 and takes advantage of the identical time of the duplicate events. Fixes #548. Closes #554. Closes #571.
This commit is contained in:
parent
8a4e939a10
commit
527952102a
@ -96,6 +96,12 @@ typedef struct _GLFWwindowX11
|
|||||||
// The last position the cursor was warped to by GLFW
|
// The last position the cursor was warped to by GLFW
|
||||||
int warpPosX, warpPosY;
|
int warpPosX, warpPosY;
|
||||||
|
|
||||||
|
// The information from the last KeyPress event
|
||||||
|
struct {
|
||||||
|
unsigned int keycode;
|
||||||
|
Time time;
|
||||||
|
} last;
|
||||||
|
|
||||||
} _GLFWwindowX11;
|
} _GLFWwindowX11;
|
||||||
|
|
||||||
|
|
||||||
|
@ -844,8 +844,13 @@ static void leaveFullscreenMode(_GLFWwindow* window)
|
|||||||
static void processEvent(XEvent *event)
|
static void processEvent(XEvent *event)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = NULL;
|
_GLFWwindow* window = NULL;
|
||||||
|
int keycode = 0;
|
||||||
Bool filtered = False;
|
Bool filtered = False;
|
||||||
|
|
||||||
|
// HACK: Save scancode as some IMs clear the field in XFilterEvent
|
||||||
|
if (event->type == KeyPress || event->type == KeyRelease)
|
||||||
|
keycode = event->xkey.keycode;
|
||||||
|
|
||||||
if (_glfw.x11.im)
|
if (_glfw.x11.im)
|
||||||
filtered = XFilterEvent(event, None);
|
filtered = XFilterEvent(event, None);
|
||||||
|
|
||||||
@ -863,28 +868,31 @@ static void processEvent(XEvent *event)
|
|||||||
{
|
{
|
||||||
case KeyPress:
|
case KeyPress:
|
||||||
{
|
{
|
||||||
const int key = translateKey(event->xkey.keycode);
|
const int key = translateKey(keycode);
|
||||||
const int mods = translateState(event->xkey.state);
|
const int mods = translateState(event->xkey.state);
|
||||||
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
|
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
|
||||||
|
|
||||||
if (window->x11.ic)
|
if (window->x11.ic)
|
||||||
{
|
{
|
||||||
int i;
|
// HACK: Ignore duplicate key press events generated by ibus
|
||||||
Status status;
|
// Corresponding release events are filtered out by the
|
||||||
wchar_t buffer[16];
|
// GLFW key repeat logic
|
||||||
|
if (window->x11.last.keycode != keycode ||
|
||||||
if (filtered)
|
window->x11.last.time != event->xkey.time)
|
||||||
{
|
{
|
||||||
// HACK: Ignore key press events intended solely for XIM
|
if (keycode)
|
||||||
if (event->xkey.keycode)
|
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
|
||||||
{
|
|
||||||
_glfwInputKey(window,
|
|
||||||
key, event->xkey.keycode,
|
|
||||||
GLFW_PRESS, mods);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
window->x11.last.keycode = keycode;
|
||||||
|
window->x11.last.time = event->xkey.time;
|
||||||
|
|
||||||
|
if (!filtered)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
Status status;
|
||||||
|
wchar_t buffer[16];
|
||||||
|
|
||||||
const int count = XwcLookupString(window->x11.ic,
|
const int count = XwcLookupString(window->x11.ic,
|
||||||
&event->xkey,
|
&event->xkey,
|
||||||
buffer, sizeof(buffer),
|
buffer, sizeof(buffer),
|
||||||
@ -899,9 +907,7 @@ static void processEvent(XEvent *event)
|
|||||||
KeySym keysym;
|
KeySym keysym;
|
||||||
XLookupString(&event->xkey, NULL, 0, &keysym, NULL);
|
XLookupString(&event->xkey, NULL, 0, &keysym, NULL);
|
||||||
|
|
||||||
_glfwInputKey(window,
|
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
|
||||||
key, event->xkey.keycode,
|
|
||||||
GLFW_PRESS, mods);
|
|
||||||
|
|
||||||
const long character = _glfwKeySym2Unicode(keysym);
|
const long character = _glfwKeySym2Unicode(keysym);
|
||||||
if (character != -1)
|
if (character != -1)
|
||||||
@ -913,7 +919,7 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
case KeyRelease:
|
case KeyRelease:
|
||||||
{
|
{
|
||||||
const int key = translateKey(event->xkey.keycode);
|
const int key = translateKey(keycode);
|
||||||
const int mods = translateState(event->xkey.state);
|
const int mods = translateState(event->xkey.state);
|
||||||
|
|
||||||
if (!_glfw.x11.xkb.detectable)
|
if (!_glfw.x11.xkb.detectable)
|
||||||
@ -929,7 +935,7 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
if (next.type == KeyPress &&
|
if (next.type == KeyPress &&
|
||||||
next.xkey.window == event->xkey.window &&
|
next.xkey.window == event->xkey.window &&
|
||||||
next.xkey.keycode == event->xkey.keycode)
|
next.xkey.keycode == keycode)
|
||||||
{
|
{
|
||||||
// HACK: Repeat events sometimes leak through due to
|
// HACK: Repeat events sometimes leak through due to
|
||||||
// some sort of time drift, so add an epsilon
|
// some sort of time drift, so add an epsilon
|
||||||
@ -947,7 +953,7 @@ static void processEvent(XEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwInputKey(window, key, event->xkey.keycode, GLFW_RELEASE, mods);
|
_glfwInputKey(window, key, keycode, GLFW_RELEASE, mods);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user