mirror of
https://github.com/SFML/SFML.git
synced 2024-11-28 14:21:04 +08:00
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,30 +362,53 @@ void WindowImplX11::Display()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplX11::ProcessEvents()
|
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
|
// Process any event in the queue matching our window
|
||||||
XEvent Event;
|
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 == KeyRelease)
|
if ((Event.type == KeyPress) || (Event.type == KeyRelease))
|
||||||
{
|
{
|
||||||
if (XPending(ourDisplay))
|
if (Event.xkey.keycode < 256)
|
||||||
{
|
{
|
||||||
XEvent NextEvent;
|
// To detect if it is a repeated key event, we check the current state of the key.
|
||||||
XPeekEvent(ourDisplay, &NextEvent);
|
// - If the state is "down", KeyReleased events must obviously be discarded.
|
||||||
if ((NextEvent.type == KeyPress) &&
|
// - KeyPress events are a little bit harder to handle: they depend on the EnableKeyRepeat state,
|
||||||
(NextEvent.xkey.keycode == Event.xkey.keycode) &&
|
// and we need to properly forward the first one.
|
||||||
(NextEvent.xkey.time == Event.xkey.time))
|
char Keys[32];
|
||||||
|
XQueryKeymap(ourDisplay, Keys);
|
||||||
|
if (Keys[Event.xkey.keycode >> 3] & (1 << (Event.xkey.keycode % 8)))
|
||||||
{
|
{
|
||||||
if (!myKeyRepeat)
|
// KeyRelease event + key down = repeated event --> discard
|
||||||
XNextEvent(ourDisplay, &NextEvent);
|
if (Event.type == KeyRelease)
|
||||||
continue;
|
{
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process the event
|
||||||
ProcessEvent(Event);
|
ProcessEvent(Event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -709,6 +732,9 @@ bool WindowImplX11::CreateContext(const VideoMode& Mode, XVisualInfo& ChosenVisu
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplX11::Initialize()
|
void WindowImplX11::Initialize()
|
||||||
{
|
{
|
||||||
|
// Make sure the "last key release" is initialized with invalid values
|
||||||
|
myLastKeyReleaseEvent.type = -1;
|
||||||
|
|
||||||
// Get the atom defining the close event
|
// Get the atom defining the close event
|
||||||
myAtomClose = XInternAtom(ourDisplay, "WM_DELETE_WINDOW", false);
|
myAtomClose = XInternAtom(ourDisplay, "WM_DELETE_WINDOW", false);
|
||||||
XSetWMProtocols(ourDisplay, myWindow, &myAtomClose, 1);
|
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
|
/// Process an incoming event from the window
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
@ -200,18 +200,6 @@ private :
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void CleanUp();
|
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
|
/// Process an incoming event from the window
|
||||||
///
|
///
|
||||||
@ -259,14 +247,15 @@ private :
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
::Window myWindow; ///< X11 structure defining our window
|
::Window myWindow; ///< X11 structure defining our window
|
||||||
bool myIsExternal; ///< Tell whether the window has been created externally or by SFML
|
bool myIsExternal; ///< Tell whether the window has been created externally or by SFML
|
||||||
GLXContext myGLContext; ///< OpenGL context attached to the window
|
GLXContext myGLContext; ///< OpenGL context attached to the window
|
||||||
Atom myAtomClose; ///< Atom used to identify the close event
|
Atom myAtomClose; ///< Atom used to identify the close event
|
||||||
int myOldVideoMode; ///< Video mode in use before we switch to fullscreen
|
int myOldVideoMode; ///< Video mode in use before we switch to fullscreen
|
||||||
Cursor myHiddenCursor; ///< As X11 doesn't provide cursor hidding, we must create a transparent one
|
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
|
XIC myInputContext; ///< Input context used to get unicode input in our window
|
||||||
bool myKeyRepeat; ///< Is the KeyRepeat feature enabled ?
|
bool myKeyRepeat; ///< Is the KeyRepeat feature enabled ?
|
||||||
|
XEvent myLastKeyReleaseEvent; ///< Last key release event we received (needed for discarding repeated key events)
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
Loading…
Reference in New Issue
Block a user