Skip to content

Commit

Permalink
Fixed the repeated keys detection algorithm on Linux
Browse files Browse the repository at this point in the history
  • Loading branch information
LaurentGomila committed Jan 3, 2013
1 parent 527bb28 commit 2285e3d
Showing 1 changed file with 28 additions and 29 deletions.
57 changes: 28 additions & 29 deletions src/SFML/Window/Linux/WindowImplX11.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -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. // Check if the key is currently down
char keys[32]; char keys[32];
XQueryKeymap(m_display, keys); XQueryKeymap(m_display, keys);
if (keys[windowEvent.xkey.keycode / 8] & (1 << (windowEvent.xkey.keycode % 8))) bool isDown = keys[windowEvent.xkey.keycode / 8] & (1 << (windowEvent.xkey.keycode % 8));
{
// KeyRelease event + key down = repeated event --> discard // Check if it's a duplicate event
if (windowEvent.type == KeyRelease) bool isDuplicate = (windowEvent.xkey.keycode == m_lastKeyReleaseEvent.xkey.keycode) &&
{ (windowEvent.xkey.time - m_lastKeyReleaseEvent.xkey.time <= 5);
m_lastKeyReleaseEvent = windowEvent;
return false; // Keep track of the last KeyRelease event
} if (windowEvent.type == KeyRelease)

m_lastKeyReleaseEvent = windowEvent;
// KeyPress event + key repeat disabled + matching KeyRelease event = repeated event --> discard
if ((windowEvent.type == KeyPress) && !m_keyRepeat && // KeyRelease event + key down or duplicate event = repeated event --> discard
(m_lastKeyReleaseEvent.xkey.keycode == windowEvent.xkey.keycode) && if ((windowEvent.type == KeyRelease) && (isDown || isDuplicate))
(m_lastKeyReleaseEvent.xkey.time == windowEvent.xkey.time)) return false;
{
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
Expand Down

0 comments on commit 2285e3d

Please sign in to comment.