Fixed the repeated keys detection algorithm on Linux

This commit is contained in:
Laurent Gomila 2013-01-03 20:31:20 +01:00
parent 527bb287a5
commit 2285e3d344

View File

@ -558,38 +558,37 @@ bool WindowImplX11::processEvent(XEvent windowEvent)
// system's key events policy doesn't match SFML's one: X server will generate // system's key events policy doesn't match SFML's one: X server will generate
// both repeated KeyPress and KeyRelease events when maintaining a key down, while // both repeated KeyPress and KeyRelease events when maintaining a key down, while
// SFML only wants repeated KeyPress events. Thus, we have to: // SFML only wants repeated KeyPress events. Thus, we have to:
// - Discard duplicated KeyRelease events when EnableKeyRepeat is true // - Discard duplicated KeyRelease events when KeyRepeatEnabled is true
// - Discard both duplicated KeyPress and KeyRelease events when EnableKeyRepeat is false // - Discard both duplicated KeyPress and KeyRelease events when KeyRepeatEnabled is false
// Detect repeated key events // Detect repeated key events
if ((windowEvent.type == KeyPress) || (windowEvent.type == KeyRelease)) if (((windowEvent.type == KeyPress) || (windowEvent.type == KeyRelease)) && (windowEvent.xkey.keycode < 256))
{ {
if (windowEvent.xkey.keycode < 256) // To detect if it is a repeated key event, we check the current state of the key:
{ // - If the state is "down", KeyReleased events must obviously be discarded
// To detect if it is a repeated key event, we check the current state of the key. // - KeyPress events are a little bit harder to handle: they depend on the KeyRepeatEnabled state,
// - If the state is "down", KeyReleased events must obviously be discarded. // and we need to properly forward the first one
// - KeyPress events are a little bit harder to handle: they depend on the EnableKeyRepeat state,
// and we need to properly forward the first one.
char keys[32];
XQueryKeymap(m_display, keys);
if (keys[windowEvent.xkey.keycode / 8] & (1 << (windowEvent.xkey.keycode % 8)))
{
// KeyRelease event + key down = repeated event --> discard
if (windowEvent.type == KeyRelease)
{
m_lastKeyReleaseEvent = windowEvent;
return false;
}
// KeyPress event + key repeat disabled + matching KeyRelease event = repeated event --> discard // Check if the key is currently down
if ((windowEvent.type == KeyPress) && !m_keyRepeat && char keys[32];
(m_lastKeyReleaseEvent.xkey.keycode == windowEvent.xkey.keycode) && XQueryKeymap(m_display, keys);
(m_lastKeyReleaseEvent.xkey.time == windowEvent.xkey.time)) bool isDown = keys[windowEvent.xkey.keycode / 8] & (1 << (windowEvent.xkey.keycode % 8));
{
return false; // Check if it's a duplicate event
} bool isDuplicate = (windowEvent.xkey.keycode == m_lastKeyReleaseEvent.xkey.keycode) &&
} (windowEvent.xkey.time - m_lastKeyReleaseEvent.xkey.time <= 5);
}
// Keep track of the last KeyRelease event
if (windowEvent.type == KeyRelease)
m_lastKeyReleaseEvent = windowEvent;
// KeyRelease event + key down or duplicate event = repeated event --> discard
if ((windowEvent.type == KeyRelease) && (isDown || isDuplicate))
return false;
// KeyPress event + matching KeyRelease event = repeated event --> discard if key repeat is disabled
if ((windowEvent.type == KeyPress) && isDuplicate && !m_keyRepeat)
return false;
} }
// Convert the X11 event to a sf::Event // Convert the X11 event to a sf::Event