Fixed Window::EnableKeyRepeat on Linux
git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/trunk@1039 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
parent
870d049bc8
commit
2ec074b12a
@ -362,28 +362,51 @@ void WindowImplX11::Display()
|
||||
////////////////////////////////////////////////////////////
|
||||
void WindowImplX11::ProcessEvents()
|
||||
{
|
||||
// This function implements a workaround to properly discard
|
||||
// repeated key events when necessary. The problem is that the
|
||||
// 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
|
||||
// SFML only wants repeated KeyPress events. Thus, we have to:
|
||||
// - Discard duplicated KeyRelease events when EnableKeyRepeat is true
|
||||
// - Discard both duplicated KeyPress and KeyRelease events when EnableKeyRepeat is false
|
||||
|
||||
|
||||
// Process any event in the queue matching our window
|
||||
XEvent Event;
|
||||
while (XCheckIfEvent(ourDisplay, &Event, &WindowImplX11::CheckEvent, reinterpret_cast<XPointer>(myWindow)))
|
||||
while (XCheckWindowEvent(ourDisplay, myWindow, ourEventMask, &Event))
|
||||
{
|
||||
// Filter repeated key events
|
||||
// Detect repeated key events
|
||||
if ((Event.type == KeyPress) || (Event.type == KeyRelease))
|
||||
{
|
||||
if (Event.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.
|
||||
// - 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(ourDisplay, Keys);
|
||||
if (Keys[Event.xkey.keycode >> 3] & (1 << (Event.xkey.keycode % 8)))
|
||||
{
|
||||
// KeyRelease event + key down = repeated event --> discard
|
||||
if (Event.type == KeyRelease)
|
||||
{
|
||||
if (XPending(ourDisplay))
|
||||
myLastKeyReleaseEvent = Event;
|
||||
continue;
|
||||
}
|
||||
|
||||
// KeyPress event + key repeat disabled + matching KeyRelease event = repeated event --> discard
|
||||
if ((Event.type == KeyPress) && !myKeyRepeat &&
|
||||
(myLastKeyReleaseEvent.xkey.keycode == Event.xkey.keycode) &&
|
||||
(myLastKeyReleaseEvent.xkey.time == Event.xkey.time))
|
||||
{
|
||||
XEvent NextEvent;
|
||||
XPeekEvent(ourDisplay, &NextEvent);
|
||||
if ((NextEvent.type == KeyPress) &&
|
||||
(NextEvent.xkey.keycode == Event.xkey.keycode) &&
|
||||
(NextEvent.xkey.time == Event.xkey.time))
|
||||
{
|
||||
if (!myKeyRepeat)
|
||||
XNextEvent(ourDisplay, &NextEvent);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process the event
|
||||
ProcessEvent(Event);
|
||||
}
|
||||
}
|
||||
@ -709,6 +732,9 @@ bool WindowImplX11::CreateContext(const VideoMode& Mode, XVisualInfo& ChosenVisu
|
||||
////////////////////////////////////////////////////////////
|
||||
void WindowImplX11::Initialize()
|
||||
{
|
||||
// Make sure the "last key release" is initialized with invalid values
|
||||
myLastKeyReleaseEvent.type = -1;
|
||||
|
||||
// Get the atom defining the close event
|
||||
myAtomClose = XInternAtom(ourDisplay, "WM_DELETE_WINDOW", false);
|
||||
XSetWMProtocols(ourDisplay, myWindow, &myAtomClose, 1);
|
||||
@ -802,17 +828,6 @@ void WindowImplX11::CleanUp()
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Filter the received events
|
||||
/// (only allow those matching a specific window)
|
||||
////////////////////////////////////////////////////////////
|
||||
Bool WindowImplX11::CheckEvent(::Display*, XEvent* Event, XPointer UserData)
|
||||
{
|
||||
// Just check if the event matches our window
|
||||
return Event->xany.window == reinterpret_cast< ::Window >(UserData);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Process an incoming event from the window
|
||||
////////////////////////////////////////////////////////////
|
||||
|
@ -200,18 +200,6 @@ private :
|
||||
////////////////////////////////////////////////////////////
|
||||
void CleanUp();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Filter the received events
|
||||
/// (only allow those matching a specific window)
|
||||
///
|
||||
/// \param Event : Event to filter
|
||||
/// \param UserData : Data passed to the function (here : the window to compare)
|
||||
///
|
||||
/// \return True if the event belongs to the specified window
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static Bool CheckEvent(::Display*, XEvent* Event, XPointer UserData);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Process an incoming event from the window
|
||||
///
|
||||
@ -267,6 +255,7 @@ private :
|
||||
Cursor myHiddenCursor; ///< As X11 doesn't provide cursor hidding, we must create a transparent one
|
||||
XIC myInputContext; ///< Input context used to get unicode input in our window
|
||||
bool myKeyRepeat; ///< Is the KeyRepeat feature enabled ?
|
||||
XEvent myLastKeyReleaseEvent; ///< Last key release event we received (needed for discarding repeated key events)
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
Loading…
Reference in New Issue
Block a user