From da8a325fa3b7d35ca4b6906bb9e313497a0974aa Mon Sep 17 00:00:00 2001 From: Andrew Mickelson Date: Sat, 13 Jun 2015 08:59:44 -0700 Subject: [PATCH 01/14] Fix keypad keys not being detected on Linux --- src/SFML/Window/Unix/InputImpl.cpp | 20 ++++++++++---------- src/SFML/Window/Unix/WindowImplX11.cpp | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/SFML/Window/Unix/InputImpl.cpp b/src/SFML/Window/Unix/InputImpl.cpp index 39491151..2ccd63d1 100644 --- a/src/SFML/Window/Unix/InputImpl.cpp +++ b/src/SFML/Window/Unix/InputImpl.cpp @@ -346,16 +346,16 @@ void InputImpl::buildMap() keycodeMap[sf::Keyboard::X] = getKeycode(XK_x); keycodeMap[sf::Keyboard::Y] = getKeycode(XK_y); keycodeMap[sf::Keyboard::Z] = getKeycode(XK_z); - keycodeMap[sf::Keyboard::Num0] = getKeycode(XK_0); - keycodeMap[sf::Keyboard::Num1] = getKeycode(XK_1); - keycodeMap[sf::Keyboard::Num2] = getKeycode(XK_2); - keycodeMap[sf::Keyboard::Num3] = getKeycode(XK_3); - keycodeMap[sf::Keyboard::Num4] = getKeycode(XK_4); - keycodeMap[sf::Keyboard::Num5] = getKeycode(XK_5); - keycodeMap[sf::Keyboard::Num6] = getKeycode(XK_6); - keycodeMap[sf::Keyboard::Num7] = getKeycode(XK_7); - keycodeMap[sf::Keyboard::Num8] = getKeycode(XK_8); - keycodeMap[sf::Keyboard::Num9] = getKeycode(XK_9); + keycodeMap[sf::Keyboard::Num0] = getKeycode(XK_KP_Insert); + keycodeMap[sf::Keyboard::Num1] = getKeycode(XK_KP_End); + keycodeMap[sf::Keyboard::Num2] = getKeycode(XK_KP_Down); + keycodeMap[sf::Keyboard::Num3] = getKeycode(XK_KP_Page_Down); + keycodeMap[sf::Keyboard::Num4] = getKeycode(XK_KP_Left); + keycodeMap[sf::Keyboard::Num5] = getKeycode(XK_KP_Begin); + keycodeMap[sf::Keyboard::Num6] = getKeycode(XK_KP_Right); + keycodeMap[sf::Keyboard::Num7] = getKeycode(XK_KP_Home); + keycodeMap[sf::Keyboard::Num8] = getKeycode(XK_KP_Up); + keycodeMap[sf::Keyboard::Num9] = getKeycode(XK_KP_Page_Up); keycodeMap[sf::Keyboard::Escape] = getKeycode(XK_Escape); keycodeMap[sf::Keyboard::LControl] = getKeycode(XK_Control_L); keycodeMap[sf::Keyboard::LShift] = getKeycode(XK_Shift_L); diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 8387975c..1f6ed09f 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -423,16 +423,16 @@ namespace case XK_Right: return sf::Keyboard::Right; case XK_Up: return sf::Keyboard::Up; case XK_Down: return sf::Keyboard::Down; - case XK_KP_0: return sf::Keyboard::Numpad0; - case XK_KP_1: return sf::Keyboard::Numpad1; - case XK_KP_2: return sf::Keyboard::Numpad2; - case XK_KP_3: return sf::Keyboard::Numpad3; - case XK_KP_4: return sf::Keyboard::Numpad4; - case XK_KP_5: return sf::Keyboard::Numpad5; - case XK_KP_6: return sf::Keyboard::Numpad6; - case XK_KP_7: return sf::Keyboard::Numpad7; - case XK_KP_8: return sf::Keyboard::Numpad8; - case XK_KP_9: return sf::Keyboard::Numpad9; + case XK_KP_Insert: return sf::Keyboard::Numpad0; + case XK_KP_End: return sf::Keyboard::Numpad1; + case XK_KP_Down: return sf::Keyboard::Numpad2; + case XK_KP_Page_Down: return sf::Keyboard::Numpad3; + case XK_KP_Left: return sf::Keyboard::Numpad4; + case XK_KP_Begin: return sf::Keyboard::Numpad5; + case XK_KP_Right: return sf::Keyboard::Numpad6; + case XK_KP_Home: return sf::Keyboard::Numpad7; + case XK_KP_Up: return sf::Keyboard::Numpad8; + case XK_KP_Page_Up: return sf::Keyboard::Numpad9; case XK_a: return sf::Keyboard::A; case XK_b: return sf::Keyboard::B; case XK_c: return sf::Keyboard::C; From b8e4b087cddf5d54b70ed620d969666a358adbc3 Mon Sep 17 00:00:00 2001 From: dawid-aurobit Date: Mon, 13 Jul 2015 18:43:47 +0200 Subject: [PATCH 02/14] convert FLAC name to upper case --- cmake/Modules/FindSFML.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Modules/FindSFML.cmake b/cmake/Modules/FindSFML.cmake index 48873ef4..937957e2 100644 --- a/cmake/Modules/FindSFML.cmake +++ b/cmake/Modules/FindSFML.cmake @@ -329,7 +329,7 @@ if(SFML_STATIC_LIBRARIES) find_sfml_dependency(VORBIS_LIBRARY "Vorbis" vorbis) find_sfml_dependency(VORBISFILE_LIBRARY "VorbisFile" vorbisfile) find_sfml_dependency(VORBISENC_LIBRARY "VorbisEnc" vorbisenc) - find_sfml_dependency(FLAC_LIBRARY "FLAC" flac) + find_sfml_dependency(FLAC_LIBRARY "FLAC" FLAC) # update the list set(SFML_AUDIO_DEPENDENCIES ${OPENAL_LIBRARY} ${FLAC_LIBRARY} ${VORBISENC_LIBRARY} ${VORBISFILE_LIBRARY} ${VORBIS_LIBRARY} ${OGG_LIBRARY}) From f6020c5f8e8baa0884029fc9629d5bdcf56d50fc Mon Sep 17 00:00:00 2001 From: Matthew Szekely Date: Tue, 14 Jul 2015 11:38:39 -0400 Subject: [PATCH 03/14] Fixed RenderTexture::clear() not always working on certain hardware --- include/SFML/Graphics/Texture.hpp | 1 + src/SFML/Graphics/RenderTarget.cpp | 5 +++++ src/SFML/Graphics/RenderTexture.cpp | 3 +++ src/SFML/Graphics/Texture.cpp | 4 ++++ 4 files changed, 13 insertions(+) diff --git a/include/SFML/Graphics/Texture.hpp b/include/SFML/Graphics/Texture.hpp index 29260d18..24715313 100644 --- a/include/SFML/Graphics/Texture.hpp +++ b/include/SFML/Graphics/Texture.hpp @@ -509,6 +509,7 @@ private: bool m_isSmooth; ///< Status of the smooth filter bool m_isRepeated; ///< Is the texture in repeat mode? mutable bool m_pixelsFlipped; ///< To work around the inconsistency in Y orientation + bool m_fboAttachment; ///< Is this texture owned by a framebuffer object? Uint64 m_cacheId; ///< Unique number that identifies the texture to the render target's cache }; diff --git a/src/SFML/Graphics/RenderTarget.cpp b/src/SFML/Graphics/RenderTarget.cpp index 19e1d505..7bb9be8d 100644 --- a/src/SFML/Graphics/RenderTarget.cpp +++ b/src/SFML/Graphics/RenderTarget.cpp @@ -281,6 +281,11 @@ void RenderTarget::draw(const Vertex* vertices, std::size_t vertexCount, if (states.shader) applyShader(NULL); + // If the texture we used to draw belonged to a RenderTexture, then forcibly unbind that texture. + // This prevents a bug where some drivers do not clear RenderTextures properly. + if (states.texture && states.texture->m_fboAttachment) + applyTexture(NULL); + // Update the cache m_cache.useVertexCache = useVertexCache; } diff --git a/src/SFML/Graphics/RenderTexture.cpp b/src/SFML/Graphics/RenderTexture.cpp index e80aa4cd..4602beb3 100644 --- a/src/SFML/Graphics/RenderTexture.cpp +++ b/src/SFML/Graphics/RenderTexture.cpp @@ -67,6 +67,9 @@ bool RenderTexture::create(unsigned int width, unsigned int height, bool depthBu { // Use frame-buffer object (FBO) m_impl = new priv::RenderTextureImplFBO; + + // Mark the texture as being a framebuffer object attachment + m_texture.m_fboAttachment = true; } else { diff --git a/src/SFML/Graphics/Texture.cpp b/src/SFML/Graphics/Texture.cpp index 610dfa2c..4be52e7b 100644 --- a/src/SFML/Graphics/Texture.cpp +++ b/src/SFML/Graphics/Texture.cpp @@ -78,6 +78,7 @@ m_texture (0), m_isSmooth (false), m_isRepeated (false), m_pixelsFlipped(false), +m_fboAttachment(false), m_cacheId (getUniqueId()) { } @@ -91,6 +92,7 @@ m_texture (0), m_isSmooth (copy.m_isSmooth), m_isRepeated (copy.m_isRepeated), m_pixelsFlipped(false), +m_fboAttachment(false), m_cacheId (getUniqueId()) { if (copy.m_texture) @@ -141,6 +143,7 @@ bool Texture::create(unsigned int width, unsigned int height) m_size.y = height; m_actualSize = actualSize; m_pixelsFlipped = false; + m_fboAttachment = false; ensureGlContext(); @@ -592,6 +595,7 @@ Texture& Texture::operator =(const Texture& right) std::swap(m_isSmooth, temp.m_isSmooth); std::swap(m_isRepeated, temp.m_isRepeated); std::swap(m_pixelsFlipped, temp.m_pixelsFlipped); + std::swap(m_fboAttachment, temp.m_fboAttachment); m_cacheId = getUniqueId(); return *this; From fa1bc737d5fd81230c9fd990148ac021b71de344 Mon Sep 17 00:00:00 2001 From: binary1248 Date: Wed, 29 Jul 2015 13:58:48 +0200 Subject: [PATCH 04/14] Reverted to Xlib event handling since XCB event handling just breaks too many things. --- src/SFML/Window/Unix/Display.cpp | 187 ------- src/SFML/Window/Unix/Display.hpp | 17 - src/SFML/Window/Unix/InputImpl.cpp | 253 ++++----- src/SFML/Window/Unix/InputImpl.hpp | 6 - src/SFML/Window/Unix/WindowImplX11.cpp | 688 +++++-------------------- src/SFML/Window/Unix/WindowImplX11.hpp | 14 +- 6 files changed, 250 insertions(+), 915 deletions(-) diff --git a/src/SFML/Window/Unix/Display.cpp b/src/SFML/Window/Unix/Display.cpp index cf1357db..c57ae0fd 100644 --- a/src/SFML/Window/Unix/Display.cpp +++ b/src/SFML/Window/Unix/Display.cpp @@ -30,8 +30,6 @@ #include #include #include -#include -#include #include @@ -43,108 +41,6 @@ namespace typedef std::map AtomMap; AtomMap atoms; - - bool mapBuilt = false; - xcb_keycode_t firstKeycode = 255; - xcb_keycode_t lastKeycode = 0; - - // We use a simple array instead of a map => constant time lookup - // xcb_keycode_t can only contain 256 distinct values - xcb_keysym_t keysymMap[256]; - - xcb_keysym_t keysymToLower(xcb_keysym_t keysym) - { - switch(keysym >> 8) - { - // Latin 1 - case 0: - { - if ((keysym >= XK_A) && (keysym <= XK_Z)) - return keysym + (XK_a - XK_A); - else if ((keysym >= XK_Agrave) && (keysym <= XK_Odiaeresis)) - return keysym + (XK_agrave - XK_Agrave); - else if ((keysym >= XK_Ooblique) && (keysym <= XK_Thorn)) - return keysym + (XK_oslash - XK_Ooblique); - break; - } - - // Latin 2 - case 1: - { - if (keysym == XK_Aogonek) - return XK_aogonek; - else if (keysym >= XK_Lstroke && keysym <= XK_Sacute) - return keysym + (XK_lstroke - XK_Lstroke); - else if (keysym >= XK_Scaron && keysym <= XK_Zacute) - return keysym + (XK_scaron - XK_Scaron); - else if (keysym >= XK_Zcaron && keysym <= XK_Zabovedot) - return keysym + (XK_zcaron - XK_Zcaron); - else if (keysym >= XK_Racute && keysym <= XK_Tcedilla) - return keysym + (XK_racute - XK_Racute); - break; - } - - // Latin 3 - case 2: - { - if (keysym >= XK_Hstroke && keysym <= XK_Hcircumflex) - return keysym + (XK_hstroke - XK_Hstroke); - else if (keysym >= XK_Gbreve && keysym <= XK_Jcircumflex) - return keysym + (XK_gbreve - XK_Gbreve); - else if (keysym >= XK_Cabovedot && keysym <= XK_Scircumflex) - return keysym + (XK_cabovedot - XK_Cabovedot); - break; - } - - // Latin 4 - case 3: - { - if (keysym >= XK_Rcedilla && keysym <= XK_Tslash) - return keysym + (XK_rcedilla - XK_Rcedilla); - else if (keysym == XK_ENG) - return XK_eng; - else if (keysym >= XK_Amacron && keysym <= XK_Umacron) - return keysym + (XK_amacron - XK_Amacron); - break; - } - - // Cyrillic - case 6: - { - if (keysym >= XK_Serbian_DJE && keysym <= XK_Serbian_DZE) - return keysym - (XK_Serbian_DJE - XK_Serbian_dje); - else if (keysym >= XK_Cyrillic_YU && keysym <= XK_Cyrillic_HARDSIGN) - return keysym - (XK_Cyrillic_YU - XK_Cyrillic_yu); - break; - } - - // Greek - case 7: - { - if (keysym >= XK_Greek_ALPHAaccent && keysym <= XK_Greek_OMEGAaccent) - return keysym + (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); - else if (keysym >= XK_Greek_ALPHA && keysym <= XK_Greek_OMEGA) - return keysym + (XK_Greek_alpha - XK_Greek_ALPHA); - break; - } - - // Armenian - case 0x14: - { - if (keysym >= XK_Armenian_AYB && keysym <= XK_Armenian_fe) { - return (keysym | 1); - } - break; - } - - default: - { - break; - } - } - - return keysym; - } } namespace sf @@ -268,89 +164,6 @@ xcb_atom_t getAtom(const std::string& name, bool onlyIfExists) return reply->atom; } - -//////////////////////////////////////////////////////////// -const xcb_keysym_t* getKeysymMap() -{ - if (!mapBuilt) - buildKeysymMap(); - - return keysymMap; -} - - -//////////////////////////////////////////////////////////// -void buildKeysymMap() -{ - // Open a connection with the X server - xcb_connection_t* connection = sf::priv::OpenConnection(); - - firstKeycode = xcb_get_setup(connection)->min_keycode; - lastKeycode = xcb_get_setup(connection)->max_keycode; - - sf::priv::ScopedXcbPtr error(NULL); - - sf::priv::ScopedXcbPtr keyboardMapping(xcb_get_keyboard_mapping_reply( - connection, - xcb_get_keyboard_mapping( - connection, - firstKeycode, - lastKeycode - firstKeycode + 1 - ), - &error - )); - - sf::priv::CloseConnection(connection); - - if (error || !keyboardMapping) - { - sf::err() << "Failed to get keyboard mapping" << std::endl; - return; - } - - uint8_t keysymsPerKeycode = keyboardMapping->keysyms_per_keycode; - - if (!keysymsPerKeycode) - { - sf::err() << "Error: No keysyms per keycode" << std::endl; - return; - } - - const xcb_keysym_t* keysyms = xcb_get_keyboard_mapping_keysyms(keyboardMapping.get()); - - if (!keysyms) - { - sf::err() << "Failed to get keyboard mapping keysyms" << std::endl; - return; - } - - xcb_keycode_t range = lastKeycode - firstKeycode + 1; - - std::fill(keysymMap, keysymMap + 256, XK_VoidSymbol); - - for (xcb_keycode_t i = firstKeycode; ; ++i) - { - const xcb_keysym_t* keysym = &keysyms[(i - firstKeycode) * keysymsPerKeycode]; - - if ((keysymsPerKeycode == 1) || (keysym[1] == XCB_NO_SYMBOL)) - { - keysymMap[i] = keysymToLower(keysym[0]); - - if (i == lastKeycode) - break; - - continue; - } - - keysymMap[i] = keysym[0]; - - if (i == lastKeycode) - break; - } - - mapBuilt = true; -} - } // namespace priv } // namespace sf diff --git a/src/SFML/Window/Unix/Display.hpp b/src/SFML/Window/Unix/Display.hpp index da29d510..2b33c964 100644 --- a/src/SFML/Window/Unix/Display.hpp +++ b/src/SFML/Window/Unix/Display.hpp @@ -116,23 +116,6 @@ xcb_window_t XCBDefaultRootWindow(xcb_connection_t* connection); //////////////////////////////////////////////////////////// xcb_atom_t getAtom(const std::string& name, bool onlyIfExists = false); -//////////////////////////////////////////////////////////// -/// \brief Get the keycode to keysym map -/// -/// Contains 255 values. Use the keycode as the index -/// into the array to retrieve its keysym. -/// -/// \return Keycode to keysym map -/// -//////////////////////////////////////////////////////////// -const xcb_keysym_t* getKeysymMap(); - -//////////////////////////////////////////////////////////// -/// \brief Build the keysym map -/// -//////////////////////////////////////////////////////////// -void buildKeysymMap(); - } // namespace priv } // namespace sf diff --git a/src/SFML/Window/Unix/InputImpl.cpp b/src/SFML/Window/Unix/InputImpl.cpp index 2ccd63d1..149adb84 100644 --- a/src/SFML/Window/Unix/InputImpl.cpp +++ b/src/SFML/Window/Unix/InputImpl.cpp @@ -32,34 +32,6 @@ #include #include #include -#include - -//////////////////////////////////////////////////////////// -// Private data -//////////////////////////////////////////////////////////// -namespace -{ - bool mapBuilt = false; - - // We use a simple array instead of a map => constant time lookup - xcb_keycode_t keycodeMap[sf::Keyboard::KeyCount]; - - xcb_keycode_t getKeycode(xcb_keysym_t keysym) - { - const xcb_keysym_t* keysymMap = sf::priv::getKeysymMap(); - - for (xcb_keycode_t i = 0; ; ++i) - { - if (keysymMap[i] == keysym) - return i; - - if (i == 255) - break; - } - - return 255; - } -} namespace sf @@ -69,15 +41,125 @@ namespace priv //////////////////////////////////////////////////////////// bool InputImpl::isKeyPressed(Keyboard::Key key) { - if (!mapBuilt) - buildMap(); + // Get the corresponding X11 keysym + KeySym keysym = 0; + switch (key) + { + case Keyboard::A: keysym = XK_A; break; + case Keyboard::B: keysym = XK_B; break; + case Keyboard::C: keysym = XK_C; break; + case Keyboard::D: keysym = XK_D; break; + case Keyboard::E: keysym = XK_E; break; + case Keyboard::F: keysym = XK_F; break; + case Keyboard::G: keysym = XK_G; break; + case Keyboard::H: keysym = XK_H; break; + case Keyboard::I: keysym = XK_I; break; + case Keyboard::J: keysym = XK_J; break; + case Keyboard::K: keysym = XK_K; break; + case Keyboard::L: keysym = XK_L; break; + case Keyboard::M: keysym = XK_M; break; + case Keyboard::N: keysym = XK_N; break; + case Keyboard::O: keysym = XK_O; break; + case Keyboard::P: keysym = XK_P; break; + case Keyboard::Q: keysym = XK_Q; break; + case Keyboard::R: keysym = XK_R; break; + case Keyboard::S: keysym = XK_S; break; + case Keyboard::T: keysym = XK_T; break; + case Keyboard::U: keysym = XK_U; break; + case Keyboard::V: keysym = XK_V; break; + case Keyboard::W: keysym = XK_W; break; + case Keyboard::X: keysym = XK_X; break; + case Keyboard::Y: keysym = XK_Y; break; + case Keyboard::Z: keysym = XK_Z; break; + case Keyboard::Num0: keysym = XK_0; break; + case Keyboard::Num1: keysym = XK_1; break; + case Keyboard::Num2: keysym = XK_2; break; + case Keyboard::Num3: keysym = XK_3; break; + case Keyboard::Num4: keysym = XK_4; break; + case Keyboard::Num5: keysym = XK_5; break; + case Keyboard::Num6: keysym = XK_6; break; + case Keyboard::Num7: keysym = XK_7; break; + case Keyboard::Num8: keysym = XK_8; break; + case Keyboard::Num9: keysym = XK_9; break; + case Keyboard::Escape: keysym = XK_Escape; break; + case Keyboard::LControl: keysym = XK_Control_L; break; + case Keyboard::LShift: keysym = XK_Shift_L; break; + case Keyboard::LAlt: keysym = XK_Alt_L; break; + case Keyboard::LSystem: keysym = XK_Super_L; break; + case Keyboard::RControl: keysym = XK_Control_R; break; + case Keyboard::RShift: keysym = XK_Shift_R; break; + case Keyboard::RAlt: keysym = XK_Alt_R; break; + case Keyboard::RSystem: keysym = XK_Super_R; break; + case Keyboard::Menu: keysym = XK_Menu; break; + case Keyboard::LBracket: keysym = XK_bracketleft; break; + case Keyboard::RBracket: keysym = XK_bracketright; break; + case Keyboard::SemiColon: keysym = XK_semicolon; break; + case Keyboard::Comma: keysym = XK_comma; break; + case Keyboard::Period: keysym = XK_period; break; + case Keyboard::Quote: keysym = XK_dead_acute; break; + case Keyboard::Slash: keysym = XK_slash; break; + case Keyboard::BackSlash: keysym = XK_backslash; break; + case Keyboard::Tilde: keysym = XK_dead_grave; break; + case Keyboard::Equal: keysym = XK_equal; break; + case Keyboard::Dash: keysym = XK_minus; break; + case Keyboard::Space: keysym = XK_space; break; + case Keyboard::Return: keysym = XK_Return; break; + case Keyboard::BackSpace: keysym = XK_BackSpace; break; + case Keyboard::Tab: keysym = XK_Tab; break; + case Keyboard::PageUp: keysym = XK_Prior; break; + case Keyboard::PageDown: keysym = XK_Next; break; + case Keyboard::End: keysym = XK_End; break; + case Keyboard::Home: keysym = XK_Home; break; + case Keyboard::Insert: keysym = XK_Insert; break; + case Keyboard::Delete: keysym = XK_Delete; break; + case Keyboard::Add: keysym = XK_KP_Add; break; + case Keyboard::Subtract: keysym = XK_KP_Subtract; break; + case Keyboard::Multiply: keysym = XK_KP_Multiply; break; + case Keyboard::Divide: keysym = XK_KP_Divide; break; + case Keyboard::Left: keysym = XK_Left; break; + case Keyboard::Right: keysym = XK_Right; break; + case Keyboard::Up: keysym = XK_Up; break; + case Keyboard::Down: keysym = XK_Down; break; + case Keyboard::Numpad0: keysym = XK_KP_0; break; + case Keyboard::Numpad1: keysym = XK_KP_1; break; + case Keyboard::Numpad2: keysym = XK_KP_2; break; + case Keyboard::Numpad3: keysym = XK_KP_3; break; + case Keyboard::Numpad4: keysym = XK_KP_4; break; + case Keyboard::Numpad5: keysym = XK_KP_5; break; + case Keyboard::Numpad6: keysym = XK_KP_6; break; + case Keyboard::Numpad7: keysym = XK_KP_7; break; + case Keyboard::Numpad8: keysym = XK_KP_8; break; + case Keyboard::Numpad9: keysym = XK_KP_9; break; + case Keyboard::F1: keysym = XK_F1; break; + case Keyboard::F2: keysym = XK_F2; break; + case Keyboard::F3: keysym = XK_F3; break; + case Keyboard::F4: keysym = XK_F4; break; + case Keyboard::F5: keysym = XK_F5; break; + case Keyboard::F6: keysym = XK_F6; break; + case Keyboard::F7: keysym = XK_F7; break; + case Keyboard::F8: keysym = XK_F8; break; + case Keyboard::F9: keysym = XK_F9; break; + case Keyboard::F10: keysym = XK_F10; break; + case Keyboard::F11: keysym = XK_F11; break; + case Keyboard::F12: keysym = XK_F12; break; + case Keyboard::F13: keysym = XK_F13; break; + case Keyboard::F14: keysym = XK_F14; break; + case Keyboard::F15: keysym = XK_F15; break; + case Keyboard::Pause: keysym = XK_Pause; break; + default: keysym = 0; break; + } // Sanity checks if (key < 0 || key >= sf::Keyboard::KeyCount) return false; + // Open a connection with the X server + Display* display = OpenDisplay(); + // Convert to keycode - xcb_keycode_t keycode = keycodeMap[key]; + xcb_keycode_t keycode = XKeysymToKeycode(display, keysym); + + CloseDisplay(display); ScopedXcbPtr error(NULL); @@ -316,115 +398,6 @@ Vector2i InputImpl::getTouchPosition(unsigned int /*finger*/, const Window& /*re return Vector2i(); } - -//////////////////////////////////////////////////////////// -void InputImpl::buildMap() -{ - keycodeMap[sf::Keyboard::A] = getKeycode(XK_a); - keycodeMap[sf::Keyboard::B] = getKeycode(XK_b); - keycodeMap[sf::Keyboard::C] = getKeycode(XK_c); - keycodeMap[sf::Keyboard::D] = getKeycode(XK_d); - keycodeMap[sf::Keyboard::E] = getKeycode(XK_e); - keycodeMap[sf::Keyboard::F] = getKeycode(XK_f); - keycodeMap[sf::Keyboard::G] = getKeycode(XK_g); - keycodeMap[sf::Keyboard::H] = getKeycode(XK_h); - keycodeMap[sf::Keyboard::I] = getKeycode(XK_i); - keycodeMap[sf::Keyboard::J] = getKeycode(XK_j); - keycodeMap[sf::Keyboard::K] = getKeycode(XK_k); - keycodeMap[sf::Keyboard::L] = getKeycode(XK_l); - keycodeMap[sf::Keyboard::M] = getKeycode(XK_m); - keycodeMap[sf::Keyboard::N] = getKeycode(XK_n); - keycodeMap[sf::Keyboard::O] = getKeycode(XK_o); - keycodeMap[sf::Keyboard::P] = getKeycode(XK_p); - keycodeMap[sf::Keyboard::Q] = getKeycode(XK_q); - keycodeMap[sf::Keyboard::R] = getKeycode(XK_r); - keycodeMap[sf::Keyboard::S] = getKeycode(XK_s); - keycodeMap[sf::Keyboard::T] = getKeycode(XK_t); - keycodeMap[sf::Keyboard::U] = getKeycode(XK_u); - keycodeMap[sf::Keyboard::V] = getKeycode(XK_v); - keycodeMap[sf::Keyboard::W] = getKeycode(XK_w); - keycodeMap[sf::Keyboard::X] = getKeycode(XK_x); - keycodeMap[sf::Keyboard::Y] = getKeycode(XK_y); - keycodeMap[sf::Keyboard::Z] = getKeycode(XK_z); - keycodeMap[sf::Keyboard::Num0] = getKeycode(XK_KP_Insert); - keycodeMap[sf::Keyboard::Num1] = getKeycode(XK_KP_End); - keycodeMap[sf::Keyboard::Num2] = getKeycode(XK_KP_Down); - keycodeMap[sf::Keyboard::Num3] = getKeycode(XK_KP_Page_Down); - keycodeMap[sf::Keyboard::Num4] = getKeycode(XK_KP_Left); - keycodeMap[sf::Keyboard::Num5] = getKeycode(XK_KP_Begin); - keycodeMap[sf::Keyboard::Num6] = getKeycode(XK_KP_Right); - keycodeMap[sf::Keyboard::Num7] = getKeycode(XK_KP_Home); - keycodeMap[sf::Keyboard::Num8] = getKeycode(XK_KP_Up); - keycodeMap[sf::Keyboard::Num9] = getKeycode(XK_KP_Page_Up); - keycodeMap[sf::Keyboard::Escape] = getKeycode(XK_Escape); - keycodeMap[sf::Keyboard::LControl] = getKeycode(XK_Control_L); - keycodeMap[sf::Keyboard::LShift] = getKeycode(XK_Shift_L); - keycodeMap[sf::Keyboard::LAlt] = getKeycode(XK_Alt_L); - keycodeMap[sf::Keyboard::LSystem] = getKeycode(XK_Super_L); - keycodeMap[sf::Keyboard::RControl] = getKeycode(XK_Control_R); - keycodeMap[sf::Keyboard::RShift] = getKeycode(XK_Shift_R); - keycodeMap[sf::Keyboard::RAlt] = getKeycode(XK_Alt_R); - keycodeMap[sf::Keyboard::RSystem] = getKeycode(XK_Super_R); - keycodeMap[sf::Keyboard::Menu] = getKeycode(XK_Menu); - keycodeMap[sf::Keyboard::LBracket] = getKeycode(XK_bracketleft); - keycodeMap[sf::Keyboard::RBracket] = getKeycode(XK_bracketright); - keycodeMap[sf::Keyboard::SemiColon] = getKeycode(XK_semicolon); - keycodeMap[sf::Keyboard::Comma] = getKeycode(XK_comma); - keycodeMap[sf::Keyboard::Period] = getKeycode(XK_period); - keycodeMap[sf::Keyboard::Quote] = getKeycode(XK_apostrophe); - keycodeMap[sf::Keyboard::Slash] = getKeycode(XK_slash); - keycodeMap[sf::Keyboard::BackSlash] = getKeycode(XK_backslash); - keycodeMap[sf::Keyboard::Tilde] = getKeycode(XK_grave); - keycodeMap[sf::Keyboard::Equal] = getKeycode(XK_equal); - keycodeMap[sf::Keyboard::Dash] = getKeycode(XK_minus); - keycodeMap[sf::Keyboard::Space] = getKeycode(XK_space); - keycodeMap[sf::Keyboard::Return] = getKeycode(XK_Return); - keycodeMap[sf::Keyboard::BackSpace] = getKeycode(XK_BackSpace); - keycodeMap[sf::Keyboard::Tab] = getKeycode(XK_Tab); - keycodeMap[sf::Keyboard::PageUp] = getKeycode(XK_Prior); - keycodeMap[sf::Keyboard::PageDown] = getKeycode(XK_Next); - keycodeMap[sf::Keyboard::End] = getKeycode(XK_End); - keycodeMap[sf::Keyboard::Home] = getKeycode(XK_Home); - keycodeMap[sf::Keyboard::Insert] = getKeycode(XK_Insert); - keycodeMap[sf::Keyboard::Delete] = getKeycode(XK_Delete); - keycodeMap[sf::Keyboard::Add] = getKeycode(XK_KP_Add); - keycodeMap[sf::Keyboard::Subtract] = getKeycode(XK_KP_Subtract); - keycodeMap[sf::Keyboard::Multiply] = getKeycode(XK_KP_Multiply); - keycodeMap[sf::Keyboard::Divide] = getKeycode(XK_KP_Divide); - keycodeMap[sf::Keyboard::Left] = getKeycode(XK_Left); - keycodeMap[sf::Keyboard::Right] = getKeycode(XK_Right); - keycodeMap[sf::Keyboard::Up] = getKeycode(XK_Up); - keycodeMap[sf::Keyboard::Down] = getKeycode(XK_Down); - keycodeMap[sf::Keyboard::Numpad0] = getKeycode(XK_KP_0); - keycodeMap[sf::Keyboard::Numpad1] = getKeycode(XK_KP_1); - keycodeMap[sf::Keyboard::Numpad2] = getKeycode(XK_KP_2); - keycodeMap[sf::Keyboard::Numpad3] = getKeycode(XK_KP_3); - keycodeMap[sf::Keyboard::Numpad4] = getKeycode(XK_KP_4); - keycodeMap[sf::Keyboard::Numpad5] = getKeycode(XK_KP_5); - keycodeMap[sf::Keyboard::Numpad6] = getKeycode(XK_KP_6); - keycodeMap[sf::Keyboard::Numpad7] = getKeycode(XK_KP_7); - keycodeMap[sf::Keyboard::Numpad8] = getKeycode(XK_KP_8); - keycodeMap[sf::Keyboard::Numpad9] = getKeycode(XK_KP_9); - keycodeMap[sf::Keyboard::F1] = getKeycode(XK_F1); - keycodeMap[sf::Keyboard::F2] = getKeycode(XK_F2); - keycodeMap[sf::Keyboard::F3] = getKeycode(XK_F3); - keycodeMap[sf::Keyboard::F4] = getKeycode(XK_F4); - keycodeMap[sf::Keyboard::F5] = getKeycode(XK_F5); - keycodeMap[sf::Keyboard::F6] = getKeycode(XK_F6); - keycodeMap[sf::Keyboard::F7] = getKeycode(XK_F7); - keycodeMap[sf::Keyboard::F8] = getKeycode(XK_F8); - keycodeMap[sf::Keyboard::F9] = getKeycode(XK_F9); - keycodeMap[sf::Keyboard::F10] = getKeycode(XK_F10); - keycodeMap[sf::Keyboard::F11] = getKeycode(XK_F11); - keycodeMap[sf::Keyboard::F12] = getKeycode(XK_F12); - keycodeMap[sf::Keyboard::F13] = getKeycode(XK_F13); - keycodeMap[sf::Keyboard::F14] = getKeycode(XK_F14); - keycodeMap[sf::Keyboard::F15] = getKeycode(XK_F15); - keycodeMap[sf::Keyboard::Pause] = getKeycode(XK_Pause); - - mapBuilt = true; -} - } // namespace priv } // namespace sf diff --git a/src/SFML/Window/Unix/InputImpl.hpp b/src/SFML/Window/Unix/InputImpl.hpp index ec4f11e9..9425c3df 100644 --- a/src/SFML/Window/Unix/InputImpl.hpp +++ b/src/SFML/Window/Unix/InputImpl.hpp @@ -158,12 +158,6 @@ public: /// //////////////////////////////////////////////////////////// static Vector2i getTouchPosition(unsigned int finger, const Window& relativeTo); - - //////////////////////////////////////////////////////////// - /// \brief Build the SFML to X11 keymap - /// - //////////////////////////////////////////////////////////// - static void buildMap(); }; } // namespace priv diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 1f6ed09f..40768136 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -47,14 +47,6 @@ #include #include -// So we don't have to require xcb dri2 to be present -#define XCB_DRI2_BUFFER_SWAP_COMPLETE 0 -#define XCB_DRI2_INVALIDATE_BUFFERS 1 - -// So we don't have to require xcb xkb to be present -#define XCB_XKB_NEW_KEYBOARD_NOTIFY 0 -#define XCB_XKB_MAP_NOTIFY 1 - #ifdef SFML_OPENGL_ES #include typedef sf::priv::EglContext ContextType; @@ -73,18 +65,19 @@ namespace sf::Mutex allWindowsMutex; sf::String windowManagerName; - bool mapBuilt = false; - - // We use a simple array instead of a map => constant time lookup - // xcb_keycode_t can only contain 256 distinct values - sf::Keyboard::Key sfKeyMap[256]; - static const unsigned long eventMask = XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW; + // Filter the events received by windows (only allow those matching a specific window) + Bool checkEvent(::Display*, XEvent* event, XPointer userData) + { + // Just check if the event matches the window + return event->xany.window == reinterpret_cast< ::Window >(userData); + } + // Find the name of the current executable std::string findExecutableName() { @@ -245,124 +238,6 @@ namespace return true; } - xcb_query_extension_reply_t getXExtension(const std::string& name) - { - xcb_connection_t* connection = sf::priv::OpenConnection(); - - sf::priv::ScopedXcbPtr error(NULL); - sf::priv::ScopedXcbPtr extension(xcb_query_extension_reply( - connection, - xcb_query_extension( - connection, - name.size(), - name.c_str() - ), - &error - )); - - // Close the connection with the X server - sf::priv::CloseConnection(connection); - - if (error || !extension || !extension->present) - { - xcb_query_extension_reply_t reply; - std::memset(&reply, 0, sizeof(reply)); - return reply; - } - - return *extension.get(); - } - - void dumpXcbExtensions() - { - xcb_connection_t* connection = sf::priv::OpenConnection(); - - sf::priv::ScopedXcbPtr error(NULL); - - // Check if the RandR extension is present - sf::priv::ScopedXcbPtr extensions(xcb_list_extensions_reply( - connection, - xcb_list_extensions( - connection - ), - &error - )); - - if (error || !extensions) - { - // Close the connection with the X server - sf::priv::CloseConnection(connection); - - sf::err() << "Couldn't get list of X extensions" << std::endl; - return; - } - - xcb_str_iterator_t iter = xcb_list_extensions_names_iterator(extensions.get()); - - sf::err() << "X Extensions:" << std::endl; - - while (iter.rem) - { - std::string name(xcb_str_name(iter.data), xcb_str_name_length(iter.data)); - - sf::priv::ScopedXcbPtr error(NULL); - - // Check if the RandR extension is present - sf::priv::ScopedXcbPtr extension(xcb_query_extension_reply( - connection, - xcb_query_extension( - connection, - name.size(), - name.c_str() - ), - &error - )); - - if (error || !extension || !extension->present) - { - sf::err() << "\t" << name << " - Failed to query" << std::endl; - continue; - } - - int firstEvent = extension->first_event; - - sf::err() << "\t" << name << " - First event: " << firstEvent << std::endl; - iter.data += xcb_str_name_length(iter.data) + 1; - --iter.rem; - } - - // Close the connection with the X server - sf::priv::CloseConnection(connection); - } - - void dumpUnhandledEvent(uint8_t type) - { - static std::vector types; - - // Check if we already reported this type - if (std::find(types.begin(), types.end(), type) != types.end()) - return; - - // Insert it if new - types.push_back(type); - - static bool dumpedExtensions = false; - - if (!dumpedExtensions) - { - dumpXcbExtensions(); - dumpedExtensions = true; - } - - sf::err() << "Unhandled event type: " << (static_cast(type) & ~0x80) << std::endl - << "Report this to the SFML maintainers if possible" << std::endl; - } - - xcb_keysym_t getKeysymFromKeycode(xcb_keycode_t keycode) - { - return sf::priv::getKeysymMap()[keycode]; - } - sf::Keyboard::Key keysymToSF(xcb_keysym_t symbol) { switch (symbol) @@ -473,27 +348,6 @@ namespace return sf::Keyboard::Unknown; } - - void buildMap() - { - for (xcb_keycode_t i = 0; ; ++i) - { - sfKeyMap[i] = keysymToSF(getKeysymFromKeycode(i)); - - if (i == 255) - break; - } - - mapBuilt = true; - } - - sf::Keyboard::Key keycodeToSF(xcb_keycode_t keycode) - { - if (!mapBuilt) - buildMap(); - - return sfKeyMap[keycode]; - } } @@ -529,7 +383,6 @@ m_fullscreen (false) ewmhSupported(); m_screen = XCBDefaultScreen(m_connection); - XSetEventQueueOwner(m_display, XCBOwnsEventQueue); // Save the window handle m_window = handle; @@ -583,7 +436,6 @@ m_fullscreen ((style & Style::Fullscreen) != 0) ewmhSupported(); m_screen = XCBDefaultScreen(m_connection); - XSetEventQueueOwner(m_display, XCBOwnsEventQueue); // Compute position and size int left = m_fullscreen ? 0 : (m_screen->width_in_pixels - mode.width) / 2; @@ -737,105 +589,10 @@ WindowHandle WindowImplX11::getSystemHandle() const //////////////////////////////////////////////////////////// void WindowImplX11::processEvents() { - // Key repeat workaround: If key repeat is enabled, XCB will spawn two - // events for each repeat interval: key release and key press. Both have - // the same timestamp and key code. We are holding back the release event - // to check for the matching key press event and if so, discard the release - // event. - - xcb_generic_event_t* event = NULL; - xcb_key_release_event_t* lastKeyReleaseEvent = NULL; - uint8_t eventType = 0; - - if (!m_xcbEvents.empty()) + XEvent event; + while (XCheckIfEvent(m_display, &event, &checkEvent, reinterpret_cast(m_window))) { - event = m_xcbEvents.front(); - m_xcbEvents.pop_front(); - } - else - { - event = xcb_poll_for_event(m_connection); - } - - while (event) - { - eventType = event->response_type & ~0x80; - - // Key was pressed and one has been released prior to that. - if (eventType == XCB_KEY_PRESS && lastKeyReleaseEvent) - { - // If the key press event matches the held back key release event, - // then we have a key repeat and discard the held back release - // event. - if (lastKeyReleaseEvent->time == reinterpret_cast(event)->time && - lastKeyReleaseEvent->detail == reinterpret_cast(event)->detail) - { - free(lastKeyReleaseEvent); - lastKeyReleaseEvent = NULL; - - // If key repeat is disabled, discard the matching key press event as well - if (!m_keyRepeat) - { - free(event); - - if (!m_xcbEvents.empty()) - { - event = m_xcbEvents.front(); - m_xcbEvents.pop_front(); - } - else - { - event = xcb_poll_for_event(m_connection); - } - - continue; - } - } - } - - // If there's still a key release event held back, process it now. - if (lastKeyReleaseEvent) - { - if (processEvent(reinterpret_cast(lastKeyReleaseEvent))) - free(lastKeyReleaseEvent); - - lastKeyReleaseEvent = NULL; - } - - if (eventType == XCB_KEY_RELEASE) - { - // Check if we're in charge of the key release - if (!passEvent(event, reinterpret_cast(event)->event)) - { - // Remember this key release event. - lastKeyReleaseEvent = reinterpret_cast(event); - event = NULL; // For safety reasons. - } - } - else - { - if (processEvent(event)) - free(event); - } - - if (!m_xcbEvents.empty()) - { - event = m_xcbEvents.front(); - m_xcbEvents.pop_front(); - } - else - { - event = xcb_poll_for_event(m_connection); - } - } - - // Process any held back release event. - if (lastKeyReleaseEvent) - { - if (processEvent(reinterpret_cast(lastKeyReleaseEvent))) - free(lastKeyReleaseEvent); - - lastKeyReleaseEvent = NULL; + processEvent(event); } } @@ -1847,28 +1604,57 @@ void WindowImplX11::cleanup() //////////////////////////////////////////////////////////// -bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) +bool WindowImplX11::processEvent(XEvent windowEvent) { + // 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 KeyRepeatEnabled is true + // - Discard both duplicated KeyPress and KeyRelease events when KeyRepeatEnabled is false + + // Detect repeated key events + // (code shamelessly taken from SDL) + if (windowEvent.type == KeyRelease) + { + // Check if there's a matching KeyPress event in the queue + XEvent nextEvent; + if (XPending(m_display)) + { + // Grab it but don't remove it from the queue, it still needs to be processed :) + XPeekEvent(m_display, &nextEvent); + if (nextEvent.type == KeyPress) + { + // 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 (!m_keyRepeat) + XNextEvent(m_display, &nextEvent); + + // This KeyRelease is a repeated event and we don't want it + return false; + } + } + } + } + // Convert the X11 event to a sf::Event - switch (windowEvent->response_type & ~0x80) + switch (windowEvent.type) { // Destroy event - case XCB_DESTROY_NOTIFY: + case DestroyNotify: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->window)) - return false; - // The window is about to be destroyed: we must cleanup resources cleanup(); break; } // Gain focus event - case XCB_FOCUS_IN: + case FocusIn: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->event)) - return false; - // Update the input context if (m_inputContext) XSetICFocus(m_inputContext); @@ -1909,11 +1695,8 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Lost focus event - case XCB_FOCUS_OUT: + case FocusOut: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->event)) - return false; - // Update the input context if (m_inputContext) XUnsetICFocus(m_inputContext); @@ -1925,56 +1708,51 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Resize event - case XCB_CONFIGURE_NOTIFY: + case ConfigureNotify: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->window)) - return false; - - // X notifies about "window configuration events", which also includes moving a window only. Check - // for a different size and only spawn a Resized event when it differs. - xcb_configure_notify_event_t* e = reinterpret_cast(windowEvent); - - if (e->width != m_previousSize.x || e->height != m_previousSize.y) + // ConfigureNotify can be triggered for other reasons, check if the size has actually changed + if ((windowEvent.xconfigure.width != m_previousSize.x) || (windowEvent.xconfigure.height != m_previousSize.y)) { - m_previousSize.x = e->width; - m_previousSize.y = e->height; - Event event; event.type = Event::Resized; - event.size.width = e->width; - event.size.height = e->height; + event.size.width = windowEvent.xconfigure.width; + event.size.height = windowEvent.xconfigure.height; pushEvent(event); + + m_previousSize.x = windowEvent.xconfigure.width; + m_previousSize.y = windowEvent.xconfigure.height; } break; } // Close event - case XCB_CLIENT_MESSAGE: + case ClientMessage: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->window)) - return false; - - xcb_client_message_event_t* e = reinterpret_cast(windowEvent); - static xcb_atom_t wmProtocols = getAtom("WM_PROTOCOLS"); // Handle window manager protocol messages we support - if (e->type == wmProtocols) + if (windowEvent.xclient.message_type == wmProtocols) { static xcb_atom_t wmDeleteWindow = getAtom("WM_DELETE_WINDOW"); static xcb_atom_t netWmPing = ewmhSupported() ? getAtom("_NET_WM_PING", true) : XCB_ATOM_NONE; - if ((e->format == 32) && (e->data.data32[0]) == static_cast(wmDeleteWindow)) + if ((windowEvent.xclient.format == 32) && (windowEvent.xclient.data.l[0]) == static_cast(wmDeleteWindow)) { // Handle the WM_DELETE_WINDOW message Event event; event.type = Event::Closed; pushEvent(event); } - else if (netWmPing && (e->format == 32) && (e->data.data32[0]) == static_cast(netWmPing)) + else if (netWmPing && (windowEvent.xclient.format == 32) && (windowEvent.xclient.data.l[0]) == static_cast(netWmPing)) { + xcb_client_message_event_t event; + // Handle the _NET_WM_PING message, send pong back to WM to show that we are responsive - e->window = XCBDefaultRootWindow(m_connection); + event.response_type = XCB_CLIENT_MESSAGE; + event.format = windowEvent.xclient.format; + event.window = XCBDefaultRootWindow(m_connection); + event.type = windowEvent.xclient.message_type; + std::memcpy(event.data.data8, windowEvent.xclient.data.b, 20); ScopedXcbPtr pongError(xcb_request_check( m_connection, @@ -1983,7 +1761,7 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) 0, XCBDefaultRootWindow(m_connection), XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, - reinterpret_cast(e) + reinterpret_cast(&event) ) )); @@ -1995,33 +1773,27 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Key down event - case XCB_KEY_PRESS: + case KeyPress: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->event)) - return false; - - xcb_key_press_event_t* e = reinterpret_cast(windowEvent); + // Get the keysym of the key that has been pressed + static XComposeStatus keyboard; + char buffer[32]; + KeySym symbol; + XLookupString(&windowEvent.xkey, buffer, sizeof(buffer), &symbol, &keyboard); // Fill the event parameters // TODO: if modifiers are wrong, use XGetModifierMapping to retrieve the actual modifiers mapping Event event; event.type = Event::KeyPressed; - event.key.code = keycodeToSF(e->detail); - event.key.alt = e->state & XCB_MOD_MASK_1; - event.key.control = e->state & XCB_MOD_MASK_CONTROL; - event.key.shift = e->state & XCB_MOD_MASK_SHIFT; - event.key.system = e->state & XCB_MOD_MASK_4; + event.key.code = keysymToSF(symbol); + event.key.alt = windowEvent.xkey.state & Mod1Mask; + event.key.control = windowEvent.xkey.state & ControlMask; + event.key.shift = windowEvent.xkey.state & ShiftMask; + event.key.system = windowEvent.xkey.state & Mod4Mask; pushEvent(event); - XEvent fakeEvent; - fakeEvent.type = KeyPress; - fakeEvent.xany.display = m_display; - fakeEvent.xany.window = e->event; - fakeEvent.xkey.state = e->state; - fakeEvent.xkey.keycode = e->detail; - // Generate a TextEntered event - if (!XFilterEvent(&fakeEvent, None)) + if (!XFilterEvent(&windowEvent, None)) { #ifdef X_HAVE_UTF8_STRING if (m_inputContext) @@ -2031,7 +1803,7 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) int length = Xutf8LookupString( m_inputContext, - &fakeEvent.xkey, + &windowEvent.xkey, reinterpret_cast(keyBuffer), sizeof(keyBuffer), NULL, @@ -2056,7 +1828,7 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) { static XComposeStatus status; char keyBuffer[16]; - if (XLookupString(&fakeEvent.xkey, keyBuffer, sizeof(keyBuffer), NULL, &status)) + if (XLookupString(&windowEvent.xkey, keyBuffer, sizeof(keyBuffer), NULL, &status)) { Event textEvent; textEvent.type = Event::TextEntered; @@ -2070,54 +1842,49 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Key up event - case XCB_KEY_RELEASE: + case KeyRelease: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->event)) - return false; - - xcb_key_release_event_t* e = reinterpret_cast(windowEvent); + // Get the keysym of the key that has been pressed + char buffer[32]; + KeySym symbol; + XLookupString(&windowEvent.xkey, buffer, 32, &symbol, NULL); // Fill the event parameters Event event; event.type = Event::KeyReleased; - event.key.code = keycodeToSF(e->detail); - event.key.alt = e->state & XCB_MOD_MASK_1; - event.key.control = e->state & XCB_MOD_MASK_CONTROL; - event.key.shift = e->state & XCB_MOD_MASK_SHIFT; - event.key.system = e->state & XCB_MOD_MASK_4; + event.key.code = keysymToSF(symbol); + event.key.alt = windowEvent.xkey.state & Mod1Mask; + event.key.control = windowEvent.xkey.state & ControlMask; + event.key.shift = windowEvent.xkey.state & ShiftMask; + event.key.system = windowEvent.xkey.state & Mod4Mask; pushEvent(event); break; } // Mouse button pressed - case XCB_BUTTON_PRESS: + case ButtonPress: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->event)) - return false; - - xcb_button_press_event_t* e = reinterpret_cast(windowEvent); - // XXX: Why button 8 and 9? // Because 4 and 5 are the vertical wheel and 6 and 7 are horizontal wheel ;) - xcb_button_t button = e->detail; - if ((button == XCB_BUTTON_INDEX_1) || - (button == XCB_BUTTON_INDEX_2) || - (button == XCB_BUTTON_INDEX_3) || + unsigned int button = windowEvent.xbutton.button; + if ((button == Button1) || + (button == Button2) || + (button == Button3) || (button == 8) || (button == 9)) { Event event; event.type = Event::MouseButtonPressed; - event.mouseButton.x = e->event_x; - event.mouseButton.y = e->event_y; + event.mouseButton.x = windowEvent.xbutton.x; + event.mouseButton.y = windowEvent.xbutton.y; switch(button) { - case XCB_BUTTON_INDEX_1: event.mouseButton.button = Mouse::Left; break; - case XCB_BUTTON_INDEX_2: event.mouseButton.button = Mouse::Middle; break; - case XCB_BUTTON_INDEX_3: event.mouseButton.button = Mouse::Right; break; - case 8: event.mouseButton.button = Mouse::XButton1; break; - case 9: event.mouseButton.button = Mouse::XButton2; break; + case Button1: event.mouseButton.button = Mouse::Left; break; + case Button2: event.mouseButton.button = Mouse::Middle; break; + case Button3: event.mouseButton.button = Mouse::Right; break; + case 8: event.mouseButton.button = Mouse::XButton1; break; + case 9: event.mouseButton.button = Mouse::XButton2; break; } pushEvent(event); } @@ -2125,49 +1892,44 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Mouse button released - case XCB_BUTTON_RELEASE: + case ButtonRelease: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->event)) - return false; - - xcb_button_release_event_t* e = reinterpret_cast(windowEvent); - - xcb_button_t button = e->detail; - if ((button == XCB_BUTTON_INDEX_1) || - (button == XCB_BUTTON_INDEX_2) || - (button == XCB_BUTTON_INDEX_3) || + unsigned int button = windowEvent.xbutton.button; + if ((button == Button1) || + (button == Button2) || + (button == Button3) || (button == 8) || (button == 9)) { Event event; event.type = Event::MouseButtonReleased; - event.mouseButton.x = e->event_x; - event.mouseButton.y = e->event_y; + event.mouseButton.x = windowEvent.xbutton.x; + event.mouseButton.y = windowEvent.xbutton.y; switch(button) { - case XCB_BUTTON_INDEX_1: event.mouseButton.button = Mouse::Left; break; - case XCB_BUTTON_INDEX_2: event.mouseButton.button = Mouse::Middle; break; - case XCB_BUTTON_INDEX_3: event.mouseButton.button = Mouse::Right; break; - case 8: event.mouseButton.button = Mouse::XButton1; break; - case 9: event.mouseButton.button = Mouse::XButton2; break; + case Button1: event.mouseButton.button = Mouse::Left; break; + case Button2: event.mouseButton.button = Mouse::Middle; break; + case Button3: event.mouseButton.button = Mouse::Right; break; + case 8: event.mouseButton.button = Mouse::XButton1; break; + case 9: event.mouseButton.button = Mouse::XButton2; break; } pushEvent(event); } - else if ((button == XCB_BUTTON_INDEX_4) || (button == XCB_BUTTON_INDEX_5)) + else if ((button == Button4) || (button == Button5)) { Event event; event.type = Event::MouseWheelMoved; - event.mouseWheel.delta = (button == XCB_BUTTON_INDEX_4) ? 1 : -1; - event.mouseWheel.x = e->event_x; - event.mouseWheel.y = e->event_y; + event.mouseWheel.delta = (button == Button4) ? 1 : -1; + event.mouseWheel.x = windowEvent.xbutton.x; + event.mouseWheel.y = windowEvent.xbutton.y; pushEvent(event); event.type = Event::MouseWheelScrolled; event.mouseWheelScroll.wheel = Mouse::VerticalWheel; - event.mouseWheelScroll.delta = (button == XCB_BUTTON_INDEX_4) ? 1 : -1; - event.mouseWheelScroll.x = e->event_x; - event.mouseWheelScroll.y = e->event_y; + event.mouseWheelScroll.delta = (button == Button4) ? 1 : -1; + event.mouseWheelScroll.x = windowEvent.xbutton.x; + event.mouseWheelScroll.y = windowEvent.xbutton.y; pushEvent(event); } else if ((button == 6) || (button == 7)) @@ -2176,37 +1938,28 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) event.type = Event::MouseWheelScrolled; event.mouseWheelScroll.wheel = Mouse::HorizontalWheel; event.mouseWheelScroll.delta = (button == 6) ? 1 : -1; - event.mouseWheelScroll.x = e->event_x; - event.mouseWheelScroll.y = e->event_y; + event.mouseWheelScroll.x = windowEvent.xbutton.x; + event.mouseWheelScroll.y = windowEvent.xbutton.y; pushEvent(event); } break; } // Mouse moved - case XCB_MOTION_NOTIFY: + case MotionNotify: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->event)) - return false; - - xcb_motion_notify_event_t* e = reinterpret_cast(windowEvent); Event event; event.type = Event::MouseMoved; - event.mouseMove.x = e->event_x; - event.mouseMove.y = e->event_y; + event.mouseMove.x = windowEvent.xmotion.x; + event.mouseMove.y = windowEvent.xmotion.y; pushEvent(event); break; } // Mouse entered - case XCB_ENTER_NOTIFY: + case EnterNotify: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->event)) - return false; - - xcb_enter_notify_event_t* enterNotifyEvent = reinterpret_cast(windowEvent); - - if (enterNotifyEvent->mode == NotifyNormal) + if (windowEvent.xcrossing.mode == NotifyNormal) { Event event; event.type = Event::MouseEntered; @@ -2216,14 +1969,9 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Mouse left - case XCB_LEAVE_NOTIFY: + case LeaveNotify: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->event)) - return false; - - xcb_leave_notify_event_t* leaveNotifyEvent = reinterpret_cast(windowEvent); - - if (leaveNotifyEvent->mode == NotifyNormal) + if (windowEvent.xcrossing.mode == NotifyNormal) { Event event; event.type = Event::MouseLeft; @@ -2233,152 +1981,15 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Parent window changed - case XCB_REPARENT_NOTIFY: + case ReparentNotify: { - if (passEvent(windowEvent, reinterpret_cast(windowEvent)->window)) - return false; - // Catch reparent events to properly apply fullscreen on // some "strange" window managers (like Awesome) which // seem to make use of temporary parents during mapping if (m_fullscreen) switchToFullscreen(); - xcb_flush(m_connection); // Discard remaining events - break; - } - - // The stuff that might pop up but we don't care about - // Whitelist more when necessary - // Window visibility changed (hide/unhide) - case XCB_MAP_NOTIFY: - case XCB_UNMAP_NOTIFY: - { - break; - } - - // Handle the rest - default: - { - uint8_t responseType = windowEvent->response_type & ~0x80; - - // Handle any extension events first - - // SHAPE - // Ubuntu's Unity desktop environment makes use of the - // Compiz compositing window manager - // Compiz seems to send SHAPE events to windows even if they - // did not specifically select those events - // We ignore those events here in order to not generate warnings - static xcb_query_extension_reply_t shapeExtension = getXExtension("SHAPE"); - if (shapeExtension.present && (responseType == shapeExtension.first_event)) - break; - - // DRI2 - static xcb_query_extension_reply_t driExtension = getXExtension("DRI2"); - if (driExtension.present) - { - // Because we are using the XCB event queue instead of the Xlib event - // queue, Mesa breaks a bit (VSync among other things) because DRI2 still - // expects certain Xlib events to come its way. We work around this by - // emulating the old Xlib event queue for these specific wire events. - // Sources (retrieved 27 Mar 2015): - // http://wrl.illest.net/post/45342765813/code-tip-glx-and-xcbownseventqueue - // https://bugs.freedesktop.org/show_bug.cgi?id=42131 - // https://bugs.freedesktop.org/show_bug.cgi?id=35945 - // Mesa src/glx/dri2.c - // QtBase src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp - // QtBase Commit bb22b4965070409df4658f16fdf549f0362e8a9c - // Qt Change-Id I3b4ef3f6e3efbae25f49f161e229e9b15e951778 - // QtBase Commit 13c5c81cfa934c9b610720fe79e07465b00ebc8d - // Qt Change-Id Ia93eb8be1cbbc3d8ae7913a934c195af6b5ec538 - // QtBase Commit decb88693c8a7f0c073889b91151f01a850e3adf - // Qt Change-Id Ic466ff26487937b03f072a57e0ee4df335492a5f - if ((responseType == driExtension.first_event + XCB_DRI2_BUFFER_SWAP_COMPLETE) || - (responseType == driExtension.first_event + XCB_DRI2_INVALIDATE_BUFFERS)) - { - // DRI2 BufferSwapComplete and InvalidateBuffers - - // We lock/unlock the display to protect against concurrent access - XLockDisplay(m_display); - - typedef Bool (*wireEventHandler)(Display*, XEvent*, xEvent*); - - // Probe for any handlers that are registered for this event type - wireEventHandler handler = XESetWireToEvent(m_display, responseType, 0); - - if (handler) - { - // Restore the previous handler if one was registered - XESetWireToEvent(m_display, responseType, handler); - - XEvent event; - windowEvent->sequence = LastKnownRequestProcessed(m_display); - - // Pretend to be the Xlib event queue - handler(m_display, &event, reinterpret_cast(windowEvent)); - } - - XUnlockDisplay(m_display); - - return true; - } - } - - // XKEYBOARD - // When the X server sends us XKEYBOARD events, it means that - // the user probably changed the layout of their keyboard - // We update our keymaps in that case - static xcb_query_extension_reply_t xkeyboardExtension = getXExtension("XKEYBOARD"); - if (xkeyboardExtension.present && (responseType == xkeyboardExtension.first_event)) - { - // We do this so we don't have to include the xkb header for the struct declaration - uint8_t xkbType = reinterpret_cast(windowEvent)[1]; - - // We only bother rebuilding our maps if the xkb mapping actually changes - if ((xkbType == XCB_XKB_NEW_KEYBOARD_NOTIFY) || (xkbType == XCB_XKB_MAP_NOTIFY)) - { - // keysym map - buildKeysymMap(); - - // keycode to SFML - buildMap(); - - // SFML to keycode - InputImpl::buildMap(); - - // XInputMethod expects keyboard mapping changes to be propagated to it - // Same idea here as with the DRI2 events above - - // We lock/unlock the display to protect against concurrent access - XLockDisplay(m_display); - - typedef Bool (*wireEventHandler)(Display*, XEvent*, xEvent*); - - // Probe for any handlers that are registered for this event type - wireEventHandler handler = XESetWireToEvent(m_display, responseType, 0); - - if (handler) - { - // Restore the previous handler if one was registered - XESetWireToEvent(m_display, responseType, handler); - - XEvent event; - windowEvent->sequence = LastKnownRequestProcessed(m_display); - - // Pretend to be the Xlib event queue - handler(m_display, &event, reinterpret_cast(windowEvent)); - } - - XUnlockDisplay(m_display); - } - - break; - } - - // Print any surprises to stderr (would be nice if people report when this happens) - dumpUnhandledEvent(responseType); - + XSync(m_display, True); // Discard remaining events break; } } @@ -2386,33 +1997,6 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) return true; } - -//////////////////////////////////////////////////////////// -bool WindowImplX11::passEvent(xcb_generic_event_t* windowEvent, xcb_window_t window) -{ - // Check if this is our event - if (window == m_window) - return false; - - Lock lock(allWindowsMutex); - - // If we are the only window, there is nobody else to pass to - if (allWindows.size() == 1) - return false; - - for (std::vector::iterator i = allWindows.begin(); i != allWindows.end(); ++i) - { - if ((*i)->m_window == window) - { - (*i)->m_xcbEvents.push_back(windowEvent); - return true; - } - } - - // It seems nobody wants the event, we'll just handle it ourselves - return false; -} - } // namespace priv } // namespace sf diff --git a/src/SFML/Window/Unix/WindowImplX11.hpp b/src/SFML/Window/Unix/WindowImplX11.hpp index 2e31fbf5..a717bfb3 100644 --- a/src/SFML/Window/Unix/WindowImplX11.hpp +++ b/src/SFML/Window/Unix/WindowImplX11.hpp @@ -301,18 +301,7 @@ private: /// \return True if the event was processed, false if it was discarded /// //////////////////////////////////////////////////////////// - bool processEvent(xcb_generic_event_t* windowEvent); - - //////////////////////////////////////////////////////////// - /// \brief Pass an incoming event to another window - /// - /// \param windowEvent Event which is being processed - /// \param window Window to pass to - /// - /// \return True if the event was passed to another window, false if it is destined for the current window - /// - //////////////////////////////////////////////////////////// - bool passEvent(xcb_generic_event_t* windowEvent, xcb_window_t window); + bool processEvent(XEvent windowEvent); //////////////////////////////////////////////////////////// // Member data @@ -323,7 +312,6 @@ private: xcb_screen_t* m_screen; ///< Screen identifier XIM m_inputMethod; ///< Input method linked to the X display XIC m_inputContext; ///< Input context used to get unicode input in our window - std::deque m_xcbEvents; ///< Events that were received in another window's loop bool m_isExternal; ///< Tell whether the window has been created externally or by SFML xcb_randr_get_screen_info_reply_t m_oldVideoMode; ///< Video mode in use before we switch to fullscreen Cursor m_hiddenCursor; ///< As X11 doesn't provide cursor hidding, we must create a transparent one From df99d5fee223d018e1a7a4c4a1f3372f76d4edf5 Mon Sep 17 00:00:00 2001 From: Mario Liebisch Date: Thu, 23 Jul 2015 09:03:15 +0200 Subject: [PATCH 05/14] Fixed image file extension detection Previously this would fail on `jpeg` and would detect something such as `notajpg` as `jpg`. This fixes #929. --- src/SFML/Graphics/ImageLoader.cpp | 55 +++++++++++++++---------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/src/SFML/Graphics/ImageLoader.cpp b/src/SFML/Graphics/ImageLoader.cpp index 08ca1472..d42be523 100644 --- a/src/SFML/Graphics/ImageLoader.cpp +++ b/src/SFML/Graphics/ImageLoader.cpp @@ -227,35 +227,34 @@ bool ImageLoader::saveImageToFile(const std::string& filename, const std::vector if (!pixels.empty() && (size.x > 0) && (size.y > 0)) { // Deduce the image type from its extension - if (filename.size() > 3) - { - // Extract the extension - std::string extension = toLower(filename.substr(filename.size() - 3)); - if (extension == "bmp") - { - // BMP format - if (stbi_write_bmp(filename.c_str(), size.x, size.y, 4, &pixels[0])) - return true; - } - else if (extension == "tga") - { - // TGA format - if (stbi_write_tga(filename.c_str(), size.x, size.y, 4, &pixels[0])) - return true; - } - else if (extension == "png") - { - // PNG format - if (stbi_write_png(filename.c_str(), size.x, size.y, 4, &pixels[0], 0)) - return true; - } - else if (extension == "jpg") - { - // JPG format - if (writeJpg(filename, pixels, size.x, size.y)) - return true; - } + // Extract the extension + const std::size_t dot = filename.find_last_of('.'); + const std::string extension = dot != std::string::npos ? toLower(filename.substr(dot + 1)) : ""; + + if (extension == "bmp") + { + // BMP format + if (stbi_write_bmp(filename.c_str(), size.x, size.y, 4, &pixels[0])) + return true; + } + else if (extension == "tga") + { + // TGA format + if (stbi_write_tga(filename.c_str(), size.x, size.y, 4, &pixels[0])) + return true; + } + else if (extension == "png") + { + // PNG format + if (stbi_write_png(filename.c_str(), size.x, size.y, 4, &pixels[0], 0)) + return true; + } + else if (extension == "jpg" || extension == "jpeg") + { + // JPG format + if (writeJpg(filename, pixels, size.x, size.y)) + return true; } } From 8f4d07319d5943f5519023c3b148c12976d4e134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Wed, 12 Aug 2015 20:22:03 +0200 Subject: [PATCH 06/14] Fixed most inconsistencies in the Unix InputImpl.cpp. --- src/SFML/Window/Unix/InputImpl.cpp | 126 ++++++++++++++--------------- 1 file changed, 63 insertions(+), 63 deletions(-) diff --git a/src/SFML/Window/Unix/InputImpl.cpp b/src/SFML/Window/Unix/InputImpl.cpp index 149adb84..53d92be3 100644 --- a/src/SFML/Window/Unix/InputImpl.cpp +++ b/src/SFML/Window/Unix/InputImpl.cpp @@ -45,63 +45,27 @@ bool InputImpl::isKeyPressed(Keyboard::Key key) KeySym keysym = 0; switch (key) { - case Keyboard::A: keysym = XK_A; break; - case Keyboard::B: keysym = XK_B; break; - case Keyboard::C: keysym = XK_C; break; - case Keyboard::D: keysym = XK_D; break; - case Keyboard::E: keysym = XK_E; break; - case Keyboard::F: keysym = XK_F; break; - case Keyboard::G: keysym = XK_G; break; - case Keyboard::H: keysym = XK_H; break; - case Keyboard::I: keysym = XK_I; break; - case Keyboard::J: keysym = XK_J; break; - case Keyboard::K: keysym = XK_K; break; - case Keyboard::L: keysym = XK_L; break; - case Keyboard::M: keysym = XK_M; break; - case Keyboard::N: keysym = XK_N; break; - case Keyboard::O: keysym = XK_O; break; - case Keyboard::P: keysym = XK_P; break; - case Keyboard::Q: keysym = XK_Q; break; - case Keyboard::R: keysym = XK_R; break; - case Keyboard::S: keysym = XK_S; break; - case Keyboard::T: keysym = XK_T; break; - case Keyboard::U: keysym = XK_U; break; - case Keyboard::V: keysym = XK_V; break; - case Keyboard::W: keysym = XK_W; break; - case Keyboard::X: keysym = XK_X; break; - case Keyboard::Y: keysym = XK_Y; break; - case Keyboard::Z: keysym = XK_Z; break; - case Keyboard::Num0: keysym = XK_0; break; - case Keyboard::Num1: keysym = XK_1; break; - case Keyboard::Num2: keysym = XK_2; break; - case Keyboard::Num3: keysym = XK_3; break; - case Keyboard::Num4: keysym = XK_4; break; - case Keyboard::Num5: keysym = XK_5; break; - case Keyboard::Num6: keysym = XK_6; break; - case Keyboard::Num7: keysym = XK_7; break; - case Keyboard::Num8: keysym = XK_8; break; - case Keyboard::Num9: keysym = XK_9; break; - case Keyboard::Escape: keysym = XK_Escape; break; - case Keyboard::LControl: keysym = XK_Control_L; break; case Keyboard::LShift: keysym = XK_Shift_L; break; - case Keyboard::LAlt: keysym = XK_Alt_L; break; - case Keyboard::LSystem: keysym = XK_Super_L; break; - case Keyboard::RControl: keysym = XK_Control_R; break; case Keyboard::RShift: keysym = XK_Shift_R; break; + case Keyboard::LControl: keysym = XK_Control_L; break; + case Keyboard::RControl: keysym = XK_Control_R; break; + case Keyboard::LAlt: keysym = XK_Alt_L; break; case Keyboard::RAlt: keysym = XK_Alt_R; break; + case Keyboard::LSystem: keysym = XK_Super_L; break; case Keyboard::RSystem: keysym = XK_Super_R; break; case Keyboard::Menu: keysym = XK_Menu; break; - case Keyboard::LBracket: keysym = XK_bracketleft; break; - case Keyboard::RBracket: keysym = XK_bracketright; break; + case Keyboard::Escape: keysym = XK_Escape; break; case Keyboard::SemiColon: keysym = XK_semicolon; break; - case Keyboard::Comma: keysym = XK_comma; break; - case Keyboard::Period: keysym = XK_period; break; - case Keyboard::Quote: keysym = XK_dead_acute; break; case Keyboard::Slash: keysym = XK_slash; break; - case Keyboard::BackSlash: keysym = XK_backslash; break; - case Keyboard::Tilde: keysym = XK_dead_grave; break; case Keyboard::Equal: keysym = XK_equal; break; case Keyboard::Dash: keysym = XK_minus; break; + case Keyboard::LBracket: keysym = XK_bracketleft; break; + case Keyboard::RBracket: keysym = XK_bracketright; break; + case Keyboard::Comma: keysym = XK_comma; break; + case Keyboard::Period: keysym = XK_period; break; + case Keyboard::Quote: keysym = XK_apostrophe; break; + case Keyboard::BackSlash: keysym = XK_backslash; break; + case Keyboard::Tilde: keysym = XK_grave; break; case Keyboard::Space: keysym = XK_space; break; case Keyboard::Return: keysym = XK_Return; break; case Keyboard::BackSpace: keysym = XK_BackSpace; break; @@ -116,20 +80,7 @@ bool InputImpl::isKeyPressed(Keyboard::Key key) case Keyboard::Subtract: keysym = XK_KP_Subtract; break; case Keyboard::Multiply: keysym = XK_KP_Multiply; break; case Keyboard::Divide: keysym = XK_KP_Divide; break; - case Keyboard::Left: keysym = XK_Left; break; - case Keyboard::Right: keysym = XK_Right; break; - case Keyboard::Up: keysym = XK_Up; break; - case Keyboard::Down: keysym = XK_Down; break; - case Keyboard::Numpad0: keysym = XK_KP_0; break; - case Keyboard::Numpad1: keysym = XK_KP_1; break; - case Keyboard::Numpad2: keysym = XK_KP_2; break; - case Keyboard::Numpad3: keysym = XK_KP_3; break; - case Keyboard::Numpad4: keysym = XK_KP_4; break; - case Keyboard::Numpad5: keysym = XK_KP_5; break; - case Keyboard::Numpad6: keysym = XK_KP_6; break; - case Keyboard::Numpad7: keysym = XK_KP_7; break; - case Keyboard::Numpad8: keysym = XK_KP_8; break; - case Keyboard::Numpad9: keysym = XK_KP_9; break; + case Keyboard::Pause: keysym = XK_Pause; break; case Keyboard::F1: keysym = XK_F1; break; case Keyboard::F2: keysym = XK_F2; break; case Keyboard::F3: keysym = XK_F3; break; @@ -145,7 +96,56 @@ bool InputImpl::isKeyPressed(Keyboard::Key key) case Keyboard::F13: keysym = XK_F13; break; case Keyboard::F14: keysym = XK_F14; break; case Keyboard::F15: keysym = XK_F15; break; - case Keyboard::Pause: keysym = XK_Pause; break; + case Keyboard::Left: keysym = XK_Left; break; + case Keyboard::Right: keysym = XK_Right; break; + case Keyboard::Up: keysym = XK_Up; break; + case Keyboard::Down: keysym = XK_Down; break; + case Keyboard::Numpad0: keysym = XK_KP_Insert; break; + case Keyboard::Numpad1: keysym = XK_KP_End; break; + case Keyboard::Numpad2: keysym = XK_KP_Down; break; + case Keyboard::Numpad3: keysym = XK_KP_Page_Down; break; + case Keyboard::Numpad4: keysym = XK_KP_Left; break; + case Keyboard::Numpad5: keysym = XK_KP_Begin; break; + case Keyboard::Numpad6: keysym = XK_KP_Right; break; + case Keyboard::Numpad7: keysym = XK_KP_Home; break; + case Keyboard::Numpad8: keysym = XK_KP_Up; break; + case Keyboard::Numpad9: keysym = XK_KP_Page_Up; break; + case Keyboard::A: keysym = XK_a; break; + case Keyboard::B: keysym = XK_b; break; + case Keyboard::C: keysym = XK_c; break; + case Keyboard::D: keysym = XK_d; break; + case Keyboard::E: keysym = XK_e; break; + case Keyboard::F: keysym = XK_f; break; + case Keyboard::G: keysym = XK_g; break; + case Keyboard::H: keysym = XK_h; break; + case Keyboard::I: keysym = XK_i; break; + case Keyboard::J: keysym = XK_j; break; + case Keyboard::K: keysym = XK_k; break; + case Keyboard::L: keysym = XK_l; break; + case Keyboard::M: keysym = XK_m; break; + case Keyboard::N: keysym = XK_n; break; + case Keyboard::O: keysym = XK_o; break; + case Keyboard::P: keysym = XK_p; break; + case Keyboard::Q: keysym = XK_q; break; + case Keyboard::R: keysym = XK_r; break; + case Keyboard::S: keysym = XK_s; break; + case Keyboard::T: keysym = XK_t; break; + case Keyboard::U: keysym = XK_u; break; + case Keyboard::V: keysym = XK_v; break; + case Keyboard::W: keysym = XK_w; break; + case Keyboard::X: keysym = XK_x; break; + case Keyboard::Y: keysym = XK_y; break; + case Keyboard::Z: keysym = XK_z; break; + case Keyboard::Num0: keysym = XK_0; break; + case Keyboard::Num1: keysym = XK_1; break; + case Keyboard::Num2: keysym = XK_2; break; + case Keyboard::Num3: keysym = XK_3; break; + case Keyboard::Num4: keysym = XK_4; break; + case Keyboard::Num5: keysym = XK_5; break; + case Keyboard::Num6: keysym = XK_6; break; + case Keyboard::Num7: keysym = XK_7; break; + case Keyboard::Num8: keysym = XK_8; break; + case Keyboard::Num9: keysym = XK_9; break; default: keysym = 0; break; } From 20756e3539d6e382ba555b9cdd3777f70df12789 Mon Sep 17 00:00:00 2001 From: Marco Antognini Date: Fri, 24 Jul 2015 22:30:36 +0200 Subject: [PATCH 07/14] Added CONTRIBUTING guidelines --- CONTRIBUTING | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 CONTRIBUTING diff --git a/CONTRIBUTING b/CONTRIBUTING new file mode 100644 index 00000000..fae5de03 --- /dev/null +++ b/CONTRIBUTING @@ -0,0 +1,16 @@ +Contribution Guidelines +======================= + +You would like to see a feature implemented or a bug fixed in SFML? Great! +Contributions to SFML are highly appreciated, be it in the form of general +ideas, concrete suggestions or code patches. + +A few guiding rules have been set up on the SFML website that you should be +aware of before opening an Issue or Pull Request. They will help you focus +on the important stuff and prevent you from losing (y)our time with requests +that are out of SFML's scope, known issues, and so on. + + http://www.sfml-dev.org/contribute.php + +Those rules cover the general scope defined for this project, a coding +style, and a precise procedure to report bugs or suggest new features. From d53a69755e778a27e6609d4eb609d8919be2c311 Mon Sep 17 00:00:00 2001 From: binary1248 Date: Fri, 14 Aug 2015 23:21:55 +0200 Subject: [PATCH 08/14] Fix _NET_WM_PING messages not being replied to properly. --- src/SFML/Window/Unix/WindowImplX11.cpp | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 40768136..7aaf4e46 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -1745,28 +1745,10 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } else if (netWmPing && (windowEvent.xclient.format == 32) && (windowEvent.xclient.data.l[0]) == static_cast(netWmPing)) { - xcb_client_message_event_t event; - // Handle the _NET_WM_PING message, send pong back to WM to show that we are responsive - event.response_type = XCB_CLIENT_MESSAGE; - event.format = windowEvent.xclient.format; - event.window = XCBDefaultRootWindow(m_connection); - event.type = windowEvent.xclient.message_type; - std::memcpy(event.data.data8, windowEvent.xclient.data.b, 20); + windowEvent.xclient.window = XCBDefaultRootWindow(m_connection); - ScopedXcbPtr pongError(xcb_request_check( - m_connection, - xcb_send_event_checked( - m_connection, - 0, - XCBDefaultRootWindow(m_connection), - XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, - reinterpret_cast(&event) - ) - )); - - if (pongError) - err() << "Could not send pong event back to WM" << std::endl; + XSendEvent(m_display, windowEvent.xclient.window, False, SubstructureNotifyMask | SubstructureRedirectMask, &windowEvent); } } break; From 110feeb7f2f78f4b8f1b51dc1b61ae1b0aece9ce Mon Sep 17 00:00:00 2001 From: Alexander Ankudinov Date: Tue, 2 Jun 2015 16:27:06 +0500 Subject: [PATCH 09/14] Fix FindSFML.cmake can't find SFML 2.1 --- cmake/Modules/FindSFML.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmake/Modules/FindSFML.cmake b/cmake/Modules/FindSFML.cmake index 937957e2..871f8662 100644 --- a/cmake/Modules/FindSFML.cmake +++ b/cmake/Modules/FindSFML.cmake @@ -89,10 +89,12 @@ if(SFML_FIND_VERSION AND SFML_INCLUDE_DIR) set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/SFML/Config.hpp") endif() FILE(READ "${SFML_CONFIG_HPP_INPUT}" SFML_CONFIG_HPP_CONTENTS) - STRING(REGEX MATCH ".*#define SFML_VERSION_MAJOR ([0-9]+).*#define SFML_VERSION_MINOR ([0-9]+).*#define SFML_VERSION_PATCH ([0-9]+).*" SFML_CONFIG_HPP_CONTENTS "${SFML_CONFIG_HPP_CONTENTS}") STRING(REGEX REPLACE ".*#define SFML_VERSION_MAJOR ([0-9]+).*" "\\1" SFML_VERSION_MAJOR "${SFML_CONFIG_HPP_CONTENTS}") STRING(REGEX REPLACE ".*#define SFML_VERSION_MINOR ([0-9]+).*" "\\1" SFML_VERSION_MINOR "${SFML_CONFIG_HPP_CONTENTS}") STRING(REGEX REPLACE ".*#define SFML_VERSION_PATCH ([0-9]+).*" "\\1" SFML_VERSION_PATCH "${SFML_CONFIG_HPP_CONTENTS}") + if (NOT "${SFML_VERSION_PATCH}" MATCHES "^[0-9]+$") + set(SFML_VERSION_PATCH 0) + endif() math(EXPR SFML_REQUESTED_VERSION "${SFML_FIND_VERSION_MAJOR} * 10000 + ${SFML_FIND_VERSION_MINOR} * 100 + ${SFML_FIND_VERSION_PATCH}") # if we could extract them, compare with the requested version number From 0bcd7d39f263a76103cee2a186882114bc5324af Mon Sep 17 00:00:00 2001 From: Jan Haller Date: Thu, 25 Jun 2015 21:38:49 +0200 Subject: [PATCH 10/14] Made implementation of glCheck and alCheck macros more robust At the moment, glCheck(...) and alCheck(...) look like a function calls, which is misleading and can cause subtle bugs, for example when used in if statements. This change mitigates the situation by allowing those expressions to be used as single statements within if/else branches. Initializations of OpenGL handles that previously involved glCheck() calls now need to be split into separate declaration and assignment. --- src/SFML/Audio/ALCheck.hpp | 3 ++- src/SFML/Graphics/GLCheck.hpp | 3 ++- src/SFML/Graphics/RenderTextureImplFBO.cpp | 3 ++- src/SFML/Graphics/Shader.cpp | 24 ++++++++++++++-------- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/SFML/Audio/ALCheck.hpp b/src/SFML/Audio/ALCheck.hpp index f8511119..34b76264 100644 --- a/src/SFML/Audio/ALCheck.hpp +++ b/src/SFML/Audio/ALCheck.hpp @@ -50,7 +50,8 @@ namespace priv #ifdef SFML_DEBUG // If in debug mode, perform a test on every call - #define alCheck(x) x; sf::priv::alCheckError(__FILE__, __LINE__); + // The do-while loop is needed so that alCheck can be used as a single statement in if/else branches + #define alCheck(expr) do { expr; sf::priv::alCheckError(__FILE__, __LINE__, #expr); } while (false) #else diff --git a/src/SFML/Graphics/GLCheck.hpp b/src/SFML/Graphics/GLCheck.hpp index 743afcb0..94e386b3 100644 --- a/src/SFML/Graphics/GLCheck.hpp +++ b/src/SFML/Graphics/GLCheck.hpp @@ -43,7 +43,8 @@ namespace priv #ifdef SFML_DEBUG // In debug mode, perform a test on every OpenGL call - #define glCheck(x) x; sf::priv::glCheckError(__FILE__, __LINE__); + // The do-while loop is needed so that glCheck can be used as a single statement in if/else branches + #define glCheck(expr) do { expr; sf::priv::glCheckError(__FILE__, __LINE__, #expr); } while (false) #else diff --git a/src/SFML/Graphics/RenderTextureImplFBO.cpp b/src/SFML/Graphics/RenderTextureImplFBO.cpp index 95268726..20ff12c0 100644 --- a/src/SFML/Graphics/RenderTextureImplFBO.cpp +++ b/src/SFML/Graphics/RenderTextureImplFBO.cpp @@ -117,7 +117,8 @@ bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsig glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0)); // A final check, just to be sure... - GLenum status = glCheck(GLEXT_glCheckFramebufferStatus(GLEXT_GL_FRAMEBUFFER)); + GLenum status; + glCheck(status = GLEXT_glCheckFramebufferStatus(GLEXT_GL_FRAMEBUFFER)); if (status != GLEXT_GL_FRAMEBUFFER_COMPLETE) { glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, 0)); diff --git a/src/SFML/Graphics/Shader.cpp b/src/SFML/Graphics/Shader.cpp index 5d87d10d..ff6a6ffe 100644 --- a/src/SFML/Graphics/Shader.cpp +++ b/src/SFML/Graphics/Shader.cpp @@ -275,7 +275,8 @@ void Shader::setParameter(const std::string& name, float x) ensureGlContext(); // Enable program - GLEXT_GLhandle program = glCheck(GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT)); + GLEXT_GLhandle program; + glCheck(program = GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT)); glCheck(GLEXT_glUseProgramObject(castToGlHandle(m_shaderProgram))); // Get parameter location and assign it new values @@ -299,7 +300,8 @@ void Shader::setParameter(const std::string& name, float x, float y) ensureGlContext(); // Enable program - GLEXT_GLhandle program = glCheck(GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT)); + GLEXT_GLhandle program; + glCheck(program = GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT)); glCheck(GLEXT_glUseProgramObject(castToGlHandle(m_shaderProgram))); // Get parameter location and assign it new values @@ -323,7 +325,8 @@ void Shader::setParameter(const std::string& name, float x, float y, float z) ensureGlContext(); // Enable program - GLEXT_GLhandle program = glCheck(GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT)); + GLEXT_GLhandle program; + glCheck(program = GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT)); glCheck(GLEXT_glUseProgramObject(castToGlHandle(m_shaderProgram))); // Get parameter location and assign it new values @@ -347,7 +350,8 @@ void Shader::setParameter(const std::string& name, float x, float y, float z, fl ensureGlContext(); // Enable program - GLEXT_GLhandle program = glCheck(GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT)); + GLEXT_GLhandle program; + glCheck(program = GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT)); glCheck(GLEXT_glUseProgramObject(castToGlHandle(m_shaderProgram))); // Get parameter location and assign it new values @@ -392,7 +396,8 @@ void Shader::setParameter(const std::string& name, const Transform& transform) ensureGlContext(); // Enable program - GLEXT_GLhandle program = glCheck(GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT)); + GLEXT_GLhandle program; + glCheck(program = GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT)); glCheck(GLEXT_glUseProgramObject(castToGlHandle(m_shaderProgram))); // Get parameter location and assign it new values @@ -534,13 +539,15 @@ bool Shader::compile(const char* vertexShaderCode, const char* fragmentShaderCod m_params.clear(); // Create the program - GLEXT_GLhandle shaderProgram = glCheck(GLEXT_glCreateProgramObject()); + GLEXT_GLhandle shaderProgram; + glCheck(shaderProgram = GLEXT_glCreateProgramObject()); // Create the vertex shader if needed if (vertexShaderCode) { // Create and compile the shader - GLEXT_GLhandle vertexShader = glCheck(GLEXT_glCreateShaderObject(GLEXT_GL_VERTEX_SHADER)); + GLEXT_GLhandle vertexShader; + glCheck(vertexShader = GLEXT_glCreateShaderObject(GLEXT_GL_VERTEX_SHADER)); glCheck(GLEXT_glShaderSource(vertexShader, 1, &vertexShaderCode, NULL)); glCheck(GLEXT_glCompileShader(vertexShader)); @@ -567,7 +574,8 @@ bool Shader::compile(const char* vertexShaderCode, const char* fragmentShaderCod if (fragmentShaderCode) { // Create and compile the shader - GLEXT_GLhandle fragmentShader = glCheck(GLEXT_glCreateShaderObject(GLEXT_GL_FRAGMENT_SHADER)); + GLEXT_GLhandle fragmentShader; + glCheck(fragmentShader = GLEXT_glCreateShaderObject(GLEXT_GL_FRAGMENT_SHADER)); glCheck(GLEXT_glShaderSource(fragmentShader, 1, &fragmentShaderCode, NULL)); glCheck(GLEXT_glCompileShader(fragmentShader)); From e5f98a6575a20465ea15647a554d72612acae027 Mon Sep 17 00:00:00 2001 From: Jan Haller Date: Thu, 25 Jun 2015 23:51:38 +0200 Subject: [PATCH 11/14] Improved diagnostic output for glCheck and alCheck macros Changes: * In addition to source file and line, the expression itself is output * For better readability, the log is split across multiple lines * alCheck() doesn't unnecessarily construct std::string when there is no error * Unused #include directives are removed --- src/SFML/Audio/ALCheck.cpp | 23 +++++++++++++---------- src/SFML/Audio/ALCheck.hpp | 9 ++++----- src/SFML/Graphics/GLCheck.cpp | 28 +++++++++++++++------------- src/SFML/Graphics/GLCheck.hpp | 8 ++++---- 4 files changed, 36 insertions(+), 32 deletions(-) diff --git a/src/SFML/Audio/ALCheck.cpp b/src/SFML/Audio/ALCheck.cpp index e1522c5c..3bb8e288 100644 --- a/src/SFML/Audio/ALCheck.cpp +++ b/src/SFML/Audio/ALCheck.cpp @@ -26,8 +26,8 @@ // Headers //////////////////////////////////////////////////////////// #include -#include #include +#include namespace sf @@ -35,14 +35,16 @@ namespace sf namespace priv { //////////////////////////////////////////////////////////// -void alCheckError(const std::string& file, unsigned int line) +void alCheckError(const char* file, unsigned int line, const char* expression) { // Get the last error ALenum errorCode = alGetError(); if (errorCode != AL_NO_ERROR) { - std::string error, description; + std::string fileString = file; + std::string error = "Unknown error"; + std::string description = "No description"; // Decode the error code switch (errorCode) @@ -50,43 +52,44 @@ void alCheckError(const std::string& file, unsigned int line) case AL_INVALID_NAME: { error = "AL_INVALID_NAME"; - description = "an unacceptable name has been specified"; + description = "A bad name (ID) has been specified."; break; } case AL_INVALID_ENUM: { error = "AL_INVALID_ENUM"; - description = "an unacceptable value has been specified for an enumerated argument"; + description = "An unacceptable value has been specified for an enumerated argument."; break; } case AL_INVALID_VALUE: { error = "AL_INVALID_VALUE"; - description = "a numeric argument is out of range"; + description = "A numeric argument is out of range."; break; } case AL_INVALID_OPERATION: { error = "AL_INVALID_OPERATION"; - description = "the specified operation is not allowed in the current state"; + description = "The specified operation is not allowed in the current state."; break; } case AL_OUT_OF_MEMORY: { error = "AL_OUT_OF_MEMORY"; - description = "there is not enough memory left to execute the command"; + description = "There is not enough memory left to execute the command."; break; } } // Log the error err() << "An internal OpenAL call failed in " - << file.substr(file.find_last_of("\\/") + 1) << " (" << line << ") : " - << error << ", " << description + << fileString.substr(fileString.find_last_of("\\/") + 1) << "(" << line << ")." + << "\nExpression:\n " << expression + << "\nError description:\n " << error << "\n " << description << "\n" << std::endl; } } diff --git a/src/SFML/Audio/ALCheck.hpp b/src/SFML/Audio/ALCheck.hpp index 34b76264..750af9ec 100644 --- a/src/SFML/Audio/ALCheck.hpp +++ b/src/SFML/Audio/ALCheck.hpp @@ -29,8 +29,6 @@ // Headers //////////////////////////////////////////////////////////// #include -#include -#include #ifdef SFML_SYSTEM_IOS #include #include @@ -45,7 +43,7 @@ namespace sf namespace priv { //////////////////////////////////////////////////////////// -/// Let's define a macro to quickly check every OpenAL API calls +/// Let's define a macro to quickly check every OpenAL API call //////////////////////////////////////////////////////////// #ifdef SFML_DEBUG @@ -56,7 +54,7 @@ namespace priv #else // Else, we don't add any overhead - #define alCheck(Func) (Func) + #define alCheck(expr) (expr) #endif @@ -66,9 +64,10 @@ namespace priv /// /// \param file Source file where the call is located /// \param line Line number of the source file where the call is located +/// \param expression The evaluated expression as a string /// //////////////////////////////////////////////////////////// -void alCheckError(const std::string& file, unsigned int line); +void alCheckError(const char* file, unsigned int line, const char* expression); } // namespace priv diff --git a/src/SFML/Graphics/GLCheck.cpp b/src/SFML/Graphics/GLCheck.cpp index ce777b2c..2a706cd8 100644 --- a/src/SFML/Graphics/GLCheck.cpp +++ b/src/SFML/Graphics/GLCheck.cpp @@ -27,6 +27,7 @@ //////////////////////////////////////////////////////////// #include #include +#include namespace sf @@ -34,16 +35,16 @@ namespace sf namespace priv { //////////////////////////////////////////////////////////// -void glCheckError(const char* file, unsigned int line) +void glCheckError(const char* file, unsigned int line, const char* expression) { // Get the last error GLenum errorCode = glGetError(); if (errorCode != GL_NO_ERROR) { - std::string fileString(file); - std::string error = "unknown error"; - std::string description = "no description"; + std::string fileString = file; + std::string error = "Unknown error"; + std::string description = "No description"; // Decode the error code switch (errorCode) @@ -51,57 +52,58 @@ void glCheckError(const char* file, unsigned int line) case GL_INVALID_ENUM: { error = "GL_INVALID_ENUM"; - description = "an unacceptable value has been specified for an enumerated argument"; + description = "An unacceptable value has been specified for an enumerated argument."; break; } case GL_INVALID_VALUE: { error = "GL_INVALID_VALUE"; - description = "a numeric argument is out of range"; + description = "A numeric argument is out of range."; break; } case GL_INVALID_OPERATION: { error = "GL_INVALID_OPERATION"; - description = "the specified operation is not allowed in the current state"; + description = "The specified operation is not allowed in the current state."; break; } case GL_STACK_OVERFLOW: { error = "GL_STACK_OVERFLOW"; - description = "this command would cause a stack overflow"; + description = "This command would cause a stack overflow."; break; } case GL_STACK_UNDERFLOW: { error = "GL_STACK_UNDERFLOW"; - description = "this command would cause a stack underflow"; + description = "This command would cause a stack underflow."; break; } case GL_OUT_OF_MEMORY: { error = "GL_OUT_OF_MEMORY"; - description = "there is not enough memory left to execute the command"; + description = "There is not enough memory left to execute the command."; break; } case GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION: { error = "GL_INVALID_FRAMEBUFFER_OPERATION"; - description = "the object bound to FRAMEBUFFER_BINDING is not \"framebuffer complete\""; + description = "The object bound to FRAMEBUFFER_BINDING is not \"framebuffer complete\"."; break; } } // Log the error err() << "An internal OpenGL call failed in " - << fileString.substr(fileString.find_last_of("\\/") + 1) << " (" << line << ") : " - << error << ", " << description + << fileString.substr(fileString.find_last_of("\\/") + 1) << "(" << line << ")." + << "\nExpression:\n " << expression + << "\nError description:\n " << error << "\n " << description << "\n" << std::endl; } } diff --git a/src/SFML/Graphics/GLCheck.hpp b/src/SFML/Graphics/GLCheck.hpp index 94e386b3..9b7db8b7 100644 --- a/src/SFML/Graphics/GLCheck.hpp +++ b/src/SFML/Graphics/GLCheck.hpp @@ -30,7 +30,6 @@ //////////////////////////////////////////////////////////// #include #include -#include namespace sf @@ -38,7 +37,7 @@ namespace sf namespace priv { //////////////////////////////////////////////////////////// -/// Let's define a macro to quickly check every OpenGL API calls +/// Let's define a macro to quickly check every OpenGL API call //////////////////////////////////////////////////////////// #ifdef SFML_DEBUG @@ -49,7 +48,7 @@ namespace priv #else // Else, we don't add any overhead - #define glCheck(call) (call) + #define glCheck(expr) (expr) #endif @@ -58,9 +57,10 @@ namespace priv /// /// \param file Source file where the call is located /// \param line Line number of the source file where the call is located +/// \param expression The evaluated expression as a string /// //////////////////////////////////////////////////////////// -void glCheckError(const char* file, unsigned int line); +void glCheckError(const char* file, unsigned int line, const char* expression); } // namespace priv From 506ec95fdeff1d697b4c1a8372fb3ae74410587d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Thu, 16 Jul 2015 15:52:01 +0200 Subject: [PATCH 12/14] Fixed a typo of the example in the font header. --- include/SFML/Graphics/Font.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/SFML/Graphics/Font.hpp b/include/SFML/Graphics/Font.hpp index 2b19d398..ac6b00eb 100644 --- a/include/SFML/Graphics/Font.hpp +++ b/include/SFML/Graphics/Font.hpp @@ -414,7 +414,7 @@ private: /// sf::Text text2; /// text2.setFont(font); /// text2.setCharacterSize(50); -/// text1.setStyle(sf::Text::Italic); +/// text2.setStyle(sf::Text::Italic); /// \endcode /// /// Apart from loading font files, and passing them to instances From 0f1dc5a7542a1794412a02744ab6afc1810bab17 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Fri, 14 Aug 2015 00:10:46 +0200 Subject: [PATCH 13/14] Fixing #935: Secure function against random data return. --- src/SFML/Graphics/RenderTarget.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/SFML/Graphics/RenderTarget.cpp b/src/SFML/Graphics/RenderTarget.cpp index 7bb9be8d..28b35e45 100644 --- a/src/SFML/Graphics/RenderTarget.cpp +++ b/src/SFML/Graphics/RenderTarget.cpp @@ -32,9 +32,9 @@ #include #include #include +#include #include - namespace { // Convert an sf::BlendMode::Factor constant to the corresponding OpenGL constant. @@ -53,6 +53,10 @@ namespace case sf::BlendMode::DstAlpha: return GL_DST_ALPHA; case sf::BlendMode::OneMinusDstAlpha: return GL_ONE_MINUS_DST_ALPHA; } + + sf::err() << "Invalid value for sf::BlendMode::Factor! Fallback to sf::BlendMode::Zero." << std::endl; + assert(false); + return GL_ZERO; } @@ -64,6 +68,10 @@ namespace case sf::BlendMode::Add: return GLEXT_GL_FUNC_ADD; case sf::BlendMode::Subtract: return GLEXT_GL_FUNC_SUBTRACT; } + + sf::err() << "Invalid value for sf::BlendMode::Equation! Fallback to sf::BlendMode::Add." << std::endl; + assert(false); + return GLEXT_GL_FUNC_ADD; } } From 01d72438debdf0ecc75260a3e7d7201c130537d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Mon, 24 Aug 2015 18:01:06 +0200 Subject: [PATCH 14/14] Increased version to 2.3.2 and add changes to changelog. --- CMakeLists.txt | 2 +- changelog.txt | 35 +++++++++++++++++++++++++++++++++++ include/SFML/Config.hpp | 2 +- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ee11ead1..c8521005 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,7 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Config.cmake) # setup version numbers set(VERSION_MAJOR 2) set(VERSION_MINOR 3) -set(VERSION_PATCH 1) +set(VERSION_PATCH 2) # add the SFML header path include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) diff --git a/changelog.txt b/changelog.txt index c6bd6613..80ded9cd 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,38 @@ +SFML 2.3.2 +========== + +Also available on the website: http://www.sfml-dev.org/changelog.php#sfml-2.3.2 + +General +======= + +* Fixed an issue where FindSFML.cmake couldn't find older versions of SFML (#903) +* Robust alCheck and glCheck macros (#917) +* Fixed FindSFML.cmake to use the uppercase FLAC name (#923) +* Added a CONTRIBUTING file so GitHub shows a message when creating a new issue (#932) + + +Window +====== + +Bugfixes +-------- +* [Linux] Fixed an issue where the keypad's key weren't being detected (#910) +* [Linux] Revert to Xlib event handling (#934) +* [Linux] Fixed XK_* inconsistency in InpuImpl.cpp (#947) +* [Linux] Fix _NET_WM_PING messages not being replied to properly (#947) + + +Graphics +======== + +Bugfixes +-------- +* Fixed clear bug on RenderTextures (#915) +* Fixed image file extension detection (#929, #930, #931) +* Secure function against random data return (#935, #942) + + SFML 2.3.1 ========== diff --git a/include/SFML/Config.hpp b/include/SFML/Config.hpp index 294f2826..05c7719e 100644 --- a/include/SFML/Config.hpp +++ b/include/SFML/Config.hpp @@ -31,7 +31,7 @@ //////////////////////////////////////////////////////////// #define SFML_VERSION_MAJOR 2 #define SFML_VERSION_MINOR 3 -#define SFML_VERSION_PATCH 1 +#define SFML_VERSION_PATCH 2 ////////////////////////////////////////////////////////////