mirror of
https://github.com/SFML/SFML.git
synced 2024-11-28 22:31:09 +08:00
Fixed X11 key repeat handling not filtering out events from other windows. (Fixes #1223)
This commit is contained in:
parent
0dd24c8f1f
commit
44944989e8
@ -77,6 +77,21 @@ namespace
|
|||||||
|
|
||||||
static const unsigned int maxTrialsCount = 5;
|
static const unsigned int maxTrialsCount = 5;
|
||||||
|
|
||||||
|
// Predicate we use to find key repeat events in processEvent
|
||||||
|
struct KeyRepeatFinder
|
||||||
|
{
|
||||||
|
KeyRepeatFinder(unsigned int keycode, Time time) : keycode(keycode), time(time) {}
|
||||||
|
|
||||||
|
// Predicate operator that checks event type, keycode and timestamp
|
||||||
|
bool operator()(const XEvent& event)
|
||||||
|
{
|
||||||
|
return ((event.type == KeyPress) && (event.xkey.keycode == keycode) && (event.xkey.time - time < 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int keycode;
|
||||||
|
Time time;
|
||||||
|
};
|
||||||
|
|
||||||
// Filter the events received by windows (only allow those matching a specific window)
|
// Filter the events received by windows (only allow those matching a specific window)
|
||||||
Bool checkEvent(::Display*, XEvent* event, XPointer userData)
|
Bool checkEvent(::Display*, XEvent* event, XPointer userData)
|
||||||
{
|
{
|
||||||
@ -752,8 +767,16 @@ WindowHandle WindowImplX11::getSystemHandle() const
|
|||||||
void WindowImplX11::processEvents()
|
void WindowImplX11::processEvents()
|
||||||
{
|
{
|
||||||
XEvent event;
|
XEvent event;
|
||||||
|
|
||||||
|
// Pick out the events that are interesting for this window
|
||||||
while (XCheckIfEvent(m_display, &event, &checkEvent, reinterpret_cast<XPointer>(m_window)))
|
while (XCheckIfEvent(m_display, &event, &checkEvent, reinterpret_cast<XPointer>(m_window)))
|
||||||
|
m_events.push_back(event);
|
||||||
|
|
||||||
|
// Handle the events for this window that we just picked out
|
||||||
|
while (!m_events.empty())
|
||||||
{
|
{
|
||||||
|
event = m_events.front();
|
||||||
|
m_events.pop_front();
|
||||||
processEvent(event);
|
processEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1533,31 +1556,25 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
|
|||||||
// - Discard both duplicated KeyPress and KeyRelease events when KeyRepeatEnabled is false
|
// - Discard both duplicated KeyPress and KeyRelease events when KeyRepeatEnabled is false
|
||||||
|
|
||||||
// Detect repeated key events
|
// Detect repeated key events
|
||||||
// (code shamelessly taken from SDL)
|
|
||||||
if (windowEvent.type == KeyRelease)
|
if (windowEvent.type == KeyRelease)
|
||||||
{
|
{
|
||||||
// Check if there's a matching KeyPress event in the queue
|
// Find the next KeyPress event with matching keycode and time
|
||||||
XEvent nextEvent;
|
std::deque<XEvent>::iterator iter = std::find_if(
|
||||||
if (XPending(m_display))
|
m_events.begin(),
|
||||||
{
|
m_events.end(),
|
||||||
// Grab it but don't remove it from the queue, it still needs to be processed :)
|
KeyRepeatFinder(windowEvent.xkey.keycode, windowEvent.xkey.time)
|
||||||
XPeekEvent(m_display, &nextEvent);
|
);
|
||||||
if (nextEvent.type == KeyPress)
|
|
||||||
{
|
if (iter != m_events.end())
|
||||||
// Check if it is a duplicated event (same timestamp as the KeyRelease event)
|
|
||||||
if ((nextEvent.xkey.keycode == windowEvent.xkey.keycode) &&
|
|
||||||
(nextEvent.xkey.time - windowEvent.xkey.time < 2))
|
|
||||||
{
|
{
|
||||||
// If we don't want repeated events, remove the next KeyPress from the queue
|
// If we don't want repeated events, remove the next KeyPress from the queue
|
||||||
if (!m_keyRepeat)
|
if (!m_keyRepeat)
|
||||||
XNextEvent(m_display, &nextEvent);
|
m_events.erase(iter);
|
||||||
|
|
||||||
// This KeyRelease is a repeated event and we don't want it
|
// This KeyRelease is a repeated event and we don't want it
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the X11 event to a sf::Event
|
// Convert the X11 event to a sf::Event
|
||||||
switch (windowEvent.type)
|
switch (windowEvent.type)
|
||||||
|
@ -272,6 +272,7 @@ private:
|
|||||||
int m_screen; ///< Screen identifier
|
int m_screen; ///< Screen identifier
|
||||||
XIM m_inputMethod; ///< Input method linked to the X display
|
XIM m_inputMethod; ///< Input method linked to the X display
|
||||||
XIC m_inputContext; ///< Input context used to get unicode input in our window
|
XIC m_inputContext; ///< Input context used to get unicode input in our window
|
||||||
|
std::deque<XEvent> m_events; ///< Queue we use to store pending events for this window
|
||||||
bool m_isExternal; ///< Tell whether the window has been created externally or by SFML
|
bool m_isExternal; ///< Tell whether the window has been created externally or by SFML
|
||||||
int m_oldVideoMode; ///< Video mode in use before we switch to fullscreen
|
int m_oldVideoMode; ///< Video mode in use before we switch to fullscreen
|
||||||
::Cursor m_hiddenCursor; ///< As X11 doesn't provide cursor hiding, we must create a transparent one
|
::Cursor m_hiddenCursor; ///< As X11 doesn't provide cursor hiding, we must create a transparent one
|
||||||
|
Loading…
Reference in New Issue
Block a user