mirror of
https://github.com/glfw/glfw.git
synced 2024-11-14 10:34:34 +00:00
X11: Fix inconsistent modifier state
Use XkbGetState to poll modifier key state mask for up-to-date modifier state after modifier KeyPress/KeyRelease events. Fixes https://github.com/glfw/glfw/issues/1630
This commit is contained in:
parent
c50d53160f
commit
96a5cd0779
@ -387,6 +387,7 @@ information on what to include when reporting a bug.
|
|||||||
(#1380)
|
(#1380)
|
||||||
- [EGL] Bugfix: The `GLFW_DOUBLEBUFFER` context attribute was ignored (#1843)
|
- [EGL] Bugfix: The `GLFW_DOUBLEBUFFER` context attribute was ignored (#1843)
|
||||||
- [GLX] Bugfix: Context creation failed if GLX 1.4 was not exported by GLX library
|
- [GLX] Bugfix: Context creation failed if GLX 1.4 was not exported by GLX library
|
||||||
|
- [X11] Bugfix: Inconsistency for Key Event Modifiers between Windows and Linux/X11
|
||||||
|
|
||||||
|
|
||||||
## Contact
|
## Contact
|
||||||
|
@ -31,6 +31,9 @@
|
|||||||
|
|
||||||
#include <X11/cursorfont.h>
|
#include <X11/cursorfont.h>
|
||||||
#include <X11/Xmd.h>
|
#include <X11/Xmd.h>
|
||||||
|
#include <X11/extensions/XKB.h>
|
||||||
|
#include <X11/XKBlib.h>
|
||||||
|
#include <X11/extensions/XKBgeom.h>
|
||||||
|
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
|
||||||
@ -210,26 +213,43 @@ static Bool isSelPropNewValueNotify(Display* display, XEvent* event, XPointer po
|
|||||||
event->xproperty.atom == notification->xselection.property;
|
event->xproperty.atom == notification->xselection.property;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translates an X event modifier state mask
|
// Polls the X11 display for up-to-date modifier key state and
|
||||||
|
// translate to GLFW modifier state mask.
|
||||||
//
|
//
|
||||||
static int translateState(int state)
|
// NB: we use this instead of the X event modifier state mask due to a
|
||||||
|
// platform quirk: modifier key press/release events don't reflect their
|
||||||
|
// own state change (e.g. pressing left control generates a KeyPress event
|
||||||
|
// WITHOUT the ctrl state bit set). https://github.com/glfw/glfw/issues/1630
|
||||||
|
//
|
||||||
|
// In the event that XKB is not available, we just translate the
|
||||||
|
// passed state argument instead.
|
||||||
|
static int getMods(int state_fallback)
|
||||||
{
|
{
|
||||||
int mods = 0;
|
int glfw_mods = 0, state;
|
||||||
|
|
||||||
|
if (_glfw.x11.xkb.available) {
|
||||||
|
XkbStateRec record;
|
||||||
|
XkbGetState(_glfw.x11.display, XkbUseCoreKbd, &record);
|
||||||
|
state = record.mods;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
state = state_fallback;
|
||||||
|
}
|
||||||
|
|
||||||
if (state & ShiftMask)
|
if (state & ShiftMask)
|
||||||
mods |= GLFW_MOD_SHIFT;
|
glfw_mods |= GLFW_MOD_SHIFT;
|
||||||
if (state & ControlMask)
|
if (state & ControlMask)
|
||||||
mods |= GLFW_MOD_CONTROL;
|
glfw_mods |= GLFW_MOD_CONTROL;
|
||||||
if (state & Mod1Mask)
|
if (state & Mod1Mask)
|
||||||
mods |= GLFW_MOD_ALT;
|
glfw_mods |= GLFW_MOD_ALT;
|
||||||
if (state & Mod4Mask)
|
if (state & Mod4Mask)
|
||||||
mods |= GLFW_MOD_SUPER;
|
glfw_mods |= GLFW_MOD_SUPER;
|
||||||
if (state & LockMask)
|
if (state & LockMask)
|
||||||
mods |= GLFW_MOD_CAPS_LOCK;
|
glfw_mods |= GLFW_MOD_CAPS_LOCK;
|
||||||
if (state & Mod2Mask)
|
if (state & Mod2Mask)
|
||||||
mods |= GLFW_MOD_NUM_LOCK;
|
glfw_mods |= GLFW_MOD_NUM_LOCK;
|
||||||
|
|
||||||
return mods;
|
return glfw_mods;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translates an X11 key code to a GLFW key token
|
// Translates an X11 key code to a GLFW key token
|
||||||
@ -1187,7 +1207,7 @@ static void processEvent(XEvent *event)
|
|||||||
case KeyPress:
|
case KeyPress:
|
||||||
{
|
{
|
||||||
const int key = translateKey(keycode);
|
const int key = translateKey(keycode);
|
||||||
const int mods = translateState(event->xkey.state);
|
const int mods = getMods(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)
|
||||||
@ -1259,7 +1279,7 @@ static void processEvent(XEvent *event)
|
|||||||
case KeyRelease:
|
case KeyRelease:
|
||||||
{
|
{
|
||||||
const int key = translateKey(keycode);
|
const int key = translateKey(keycode);
|
||||||
const int mods = translateState(event->xkey.state);
|
const int mods = getMods(event->xkey.state);
|
||||||
|
|
||||||
if (!_glfw.x11.xkb.detectable)
|
if (!_glfw.x11.xkb.detectable)
|
||||||
{
|
{
|
||||||
@ -1299,7 +1319,7 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
case ButtonPress:
|
case ButtonPress:
|
||||||
{
|
{
|
||||||
const int mods = translateState(event->xbutton.state);
|
const int mods = getMods(event->xbutton.state);
|
||||||
|
|
||||||
if (event->xbutton.button == Button1)
|
if (event->xbutton.button == Button1)
|
||||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods);
|
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods);
|
||||||
@ -1333,7 +1353,7 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
case ButtonRelease:
|
case ButtonRelease:
|
||||||
{
|
{
|
||||||
const int mods = translateState(event->xbutton.state);
|
const int mods = getMods(event->xbutton.state);
|
||||||
|
|
||||||
if (event->xbutton.button == Button1)
|
if (event->xbutton.button == Button1)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user