diff options
author | James Cowgill <james410@cowgill.org.uk> | 2015-09-12 23:54:56 +0100 |
---|---|---|
committer | James Cowgill <james410@cowgill.org.uk> | 2015-09-12 23:54:56 +0100 |
commit | 301fd78b3ac87cf1fbce9d2c955db89094a304a5 (patch) | |
tree | ca19b5d935af18b7e5da4beaa2f4b150a1192833 | |
parent | 232f6c9906817eee494907d7bbe8ddf2dacf8fbf (diff) |
Imported Upstream version 2.3.2+dfsg
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | CONTRIBUTING | 16 | ||||
-rw-r--r-- | changelog.txt | 35 | ||||
-rw-r--r-- | cmake/Modules/FindSFML.cmake | 6 | ||||
-rw-r--r-- | include/SFML/Config.hpp | 2 | ||||
-rw-r--r-- | include/SFML/Graphics/Font.hpp | 2 | ||||
-rw-r--r-- | include/SFML/Graphics/Texture.hpp | 1 | ||||
-rw-r--r-- | src/SFML/Audio/ALCheck.cpp | 23 | ||||
-rw-r--r-- | src/SFML/Audio/ALCheck.hpp | 12 | ||||
-rw-r--r-- | src/SFML/Graphics/GLCheck.cpp | 28 | ||||
-rw-r--r-- | src/SFML/Graphics/GLCheck.hpp | 11 | ||||
-rw-r--r-- | src/SFML/Graphics/ImageLoader.cpp | 55 | ||||
-rw-r--r-- | src/SFML/Graphics/RenderTarget.cpp | 15 | ||||
-rw-r--r-- | src/SFML/Graphics/RenderTexture.cpp | 3 | ||||
-rw-r--r-- | src/SFML/Graphics/RenderTextureImplFBO.cpp | 3 | ||||
-rw-r--r-- | src/SFML/Graphics/Shader.cpp | 24 | ||||
-rw-r--r-- | src/SFML/Graphics/Texture.cpp | 4 | ||||
-rw-r--r-- | src/SFML/Window/Unix/Display.cpp | 187 | ||||
-rw-r--r-- | src/SFML/Window/Unix/Display.hpp | 17 | ||||
-rw-r--r-- | src/SFML/Window/Unix/InputImpl.cpp | 253 | ||||
-rw-r--r-- | src/SFML/Window/Unix/InputImpl.hpp | 6 | ||||
-rw-r--r-- | src/SFML/Window/Unix/WindowImplX11.cpp | 716 | ||||
-rw-r--r-- | src/SFML/Window/Unix/WindowImplX11.hpp | 14 |
23 files changed, 420 insertions, 1015 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index ee11ead..c852100 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/CONTRIBUTING b/CONTRIBUTING new file mode 100644 index 0000000..fae5de0 --- /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. diff --git a/changelog.txt b/changelog.txt index c6bd661..80ded9c 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/cmake/Modules/FindSFML.cmake b/cmake/Modules/FindSFML.cmake index 48873ef..871f866 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 @@ -329,7 +331,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}) diff --git a/include/SFML/Config.hpp b/include/SFML/Config.hpp index 294f282..05c7719 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 //////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Font.hpp b/include/SFML/Graphics/Font.hpp index 2b19d39..ac6b00e 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 diff --git a/include/SFML/Graphics/Texture.hpp b/include/SFML/Graphics/Texture.hpp index 29260d1..2471531 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/Audio/ALCheck.cpp b/src/SFML/Audio/ALCheck.cpp index e1522c5..3bb8e28 100644 --- a/src/SFML/Audio/ALCheck.cpp +++ b/src/SFML/Audio/ALCheck.cpp @@ -26,8 +26,8 @@ // Headers //////////////////////////////////////////////////////////// #include <SFML/Audio/ALCheck.hpp> -#include <SFML/Audio/AudioDevice.hpp> #include <SFML/System/Err.hpp> +#include <string> 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 f851111..750af9e 100644 --- a/src/SFML/Audio/ALCheck.hpp +++ b/src/SFML/Audio/ALCheck.hpp @@ -29,8 +29,6 @@ // Headers //////////////////////////////////////////////////////////// #include <SFML/Config.hpp> -#include <iostream> -#include <string> #ifdef SFML_SYSTEM_IOS #include <OpenAl/al.h> #include <OpenAl/alc.h> @@ -45,17 +43,18 @@ 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 // 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 // Else, we don't add any overhead - #define alCheck(Func) (Func) + #define alCheck(expr) (expr) #endif @@ -65,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 ce777b2..2a706cd 100644 --- a/src/SFML/Graphics/GLCheck.cpp +++ b/src/SFML/Graphics/GLCheck.cpp @@ -27,6 +27,7 @@ //////////////////////////////////////////////////////////// #include <SFML/Graphics/GLCheck.hpp> #include <SFML/System/Err.hpp> +#include <string> 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 743afcb..9b7db8b 100644 --- a/src/SFML/Graphics/GLCheck.hpp +++ b/src/SFML/Graphics/GLCheck.hpp @@ -30,7 +30,6 @@ //////////////////////////////////////////////////////////// #include <SFML/Config.hpp> #include <SFML/Graphics/GLExtensions.hpp> -#include <string> namespace sf @@ -38,17 +37,18 @@ 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 // 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 // Else, we don't add any overhead - #define glCheck(call) (call) + #define glCheck(expr) (expr) #endif @@ -57,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 diff --git a/src/SFML/Graphics/ImageLoader.cpp b/src/SFML/Graphics/ImageLoader.cpp index 08ca147..d42be52 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 + 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") { - // 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; - } + // JPG format + if (writeJpg(filename, pixels, size.x, size.y)) + return true; } } diff --git a/src/SFML/Graphics/RenderTarget.cpp b/src/SFML/Graphics/RenderTarget.cpp index 19e1d50..28b35e4 100644 --- a/src/SFML/Graphics/RenderTarget.cpp +++ b/src/SFML/Graphics/RenderTarget.cpp @@ -32,9 +32,9 @@ #include <SFML/Graphics/VertexArray.hpp> #include <SFML/Graphics/GLCheck.hpp> #include <SFML/System/Err.hpp> +#include <cassert> #include <iostream> - 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; } } @@ -281,6 +289,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 e80aa4c..4602beb 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/RenderTextureImplFBO.cpp b/src/SFML/Graphics/RenderTextureImplFBO.cpp index 9526872..20ff12c 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 5d87d10..ff6a6ff 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)); diff --git a/src/SFML/Graphics/Texture.cpp b/src/SFML/Graphics/Texture.cpp index 610dfa2..4be52e7 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; diff --git a/src/SFML/Window/Unix/Display.cpp b/src/SFML/Window/Unix/Display.cpp index cf1357d..c57ae0f 100644 --- a/src/SFML/Window/Unix/Display.cpp +++ b/src/SFML/Window/Unix/Display.cpp @@ -30,8 +30,6 @@ #include <SFML/Window/Unix/ScopedXcbPtr.hpp> #include <X11/keysym.h> #include <cassert> -#include <cstdlib> -#include <algorithm> #include <map> @@ -43,108 +41,6 @@ namespace typedef std::map<std::string, xcb_atom_t> 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<xcb_generic_error_t> error(NULL); - - sf::priv::ScopedXcbPtr<xcb_get_keyboard_mapping_reply_t> 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 da29d51..2b33c96 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 3949115..53d92be 100644 --- a/src/SFML/Window/Unix/InputImpl.cpp +++ b/src/SFML/Window/Unix/InputImpl.cpp @@ -32,34 +32,6 @@ #include <SFML/System/Err.hpp> #include <xcb/xcb.h> #include <X11/keysym.h> -#include <cstdlib> - -//////////////////////////////////////////////////////////// -// 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::LShift: keysym = XK_Shift_L; 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::Escape: keysym = XK_Escape; break; + case Keyboard::SemiColon: keysym = XK_semicolon; break; + case Keyboard::Slash: keysym = XK_slash; 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; + 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::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; + 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::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; + } // 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<xcb_generic_error_t> 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_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::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 ec4f11e..9425c3d 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 8387975..7aaf4e4 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -47,14 +47,6 @@ #include <string> #include <cstring> -// 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 <SFML/Window/EglContext.hpp> 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<xcb_generic_error_t> error(NULL); - sf::priv::ScopedXcbPtr<xcb_query_extension_reply_t> 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<xcb_generic_error_t> error(NULL); - - // Check if the RandR extension is present - sf::priv::ScopedXcbPtr<xcb_list_extensions_reply_t> 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<xcb_generic_error_t> error(NULL); - - // Check if the RandR extension is present - sf::priv::ScopedXcbPtr<xcb_query_extension_reply_t> 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<uint8_t> 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<int>(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) @@ -423,16 +298,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; @@ -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<XPointer>(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<xcb_key_press_event_t*>(event)->time && - lastKeyReleaseEvent->detail == reinterpret_cast<xcb_key_press_event_t*>(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<xcb_generic_event_t*>(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<xcb_key_release_event_t*>(event)->event)) - { - // Remember this key release event. - lastKeyReleaseEvent = reinterpret_cast<xcb_key_release_event_t*>(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<xcb_generic_event_t*>(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<xcb_destroy_notify_event_t*>(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<xcb_focus_in_event_t*>(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<xcb_focus_out_event_t*>(windowEvent)->event)) - return false; - // Update the input context if (m_inputContext) XUnsetICFocus(m_inputContext); @@ -1925,103 +1708,74 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Resize event - case XCB_CONFIGURE_NOTIFY: + case ConfigureNotify: { - if (passEvent(windowEvent, reinterpret_cast<xcb_configure_notify_event_t*>(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<xcb_configure_notify_event_t*>(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<xcb_client_message_event_t*>(windowEvent)->window)) - return false; - - xcb_client_message_event_t* e = reinterpret_cast<xcb_client_message_event_t*>(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<long>(wmDeleteWindow)) + if ((windowEvent.xclient.format == 32) && (windowEvent.xclient.data.l[0]) == static_cast<long>(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<long>(netWmPing)) + else if (netWmPing && (windowEvent.xclient.format == 32) && (windowEvent.xclient.data.l[0]) == static_cast<long>(netWmPing)) { // Handle the _NET_WM_PING message, send pong back to WM to show that we are responsive - e->window = XCBDefaultRootWindow(m_connection); - - ScopedXcbPtr<xcb_generic_error_t> 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<char*>(e) - ) - )); - - if (pongError) - err() << "Could not send pong event back to WM" << std::endl; + windowEvent.xclient.window = XCBDefaultRootWindow(m_connection); + + XSendEvent(m_display, windowEvent.xclient.window, False, SubstructureNotifyMask | SubstructureRedirectMask, &windowEvent); } } break; } // Key down event - case XCB_KEY_PRESS: + case KeyPress: { - if (passEvent(windowEvent, reinterpret_cast<xcb_key_press_event_t*>(windowEvent)->event)) - return false; - - xcb_key_press_event_t* e = reinterpret_cast<xcb_key_press_event_t*>(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 +1785,7 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) int length = Xutf8LookupString( m_inputContext, - &fakeEvent.xkey, + &windowEvent.xkey, reinterpret_cast<char*>(keyBuffer), sizeof(keyBuffer), NULL, @@ -2056,7 +1810,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 +1824,49 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Key up event - case XCB_KEY_RELEASE: + case KeyRelease: { - if (passEvent(windowEvent, reinterpret_cast<xcb_key_release_event_t*>(windowEvent)->event)) - return false; - - xcb_key_release_event_t* e = reinterpret_cast<xcb_key_release_event_t*>(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<xcb_button_press_event_t*>(windowEvent)->event)) - return false; - - xcb_button_press_event_t* e = reinterpret_cast<xcb_button_press_event_t*>(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 +1874,44 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Mouse button released - case XCB_BUTTON_RELEASE: + case ButtonRelease: { - if (passEvent(windowEvent, reinterpret_cast<xcb_button_release_event_t*>(windowEvent)->event)) - return false; - - xcb_button_release_event_t* e = reinterpret_cast<xcb_button_press_event_t*>(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 +1920,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<xcb_motion_notify_event_t*>(windowEvent)->event)) - return false; - - xcb_motion_notify_event_t* e = reinterpret_cast<xcb_motion_notify_event_t*>(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<xcb_enter_notify_event_t*>(windowEvent)->event)) - return false; - - xcb_enter_notify_event_t* enterNotifyEvent = reinterpret_cast<xcb_enter_notify_event_t*>(windowEvent); - - if (enterNotifyEvent->mode == NotifyNormal) + if (windowEvent.xcrossing.mode == NotifyNormal) { Event event; event.type = Event::MouseEntered; @@ -2216,14 +1951,9 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Mouse left - case XCB_LEAVE_NOTIFY: + case LeaveNotify: { - if (passEvent(windowEvent, reinterpret_cast<xcb_leave_notify_event_t*>(windowEvent)->event)) - return false; - - xcb_leave_notify_event_t* leaveNotifyEvent = reinterpret_cast<xcb_leave_notify_event_t*>(windowEvent); - - if (leaveNotifyEvent->mode == NotifyNormal) + if (windowEvent.xcrossing.mode == NotifyNormal) { Event event; event.type = Event::MouseLeft; @@ -2233,152 +1963,15 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } // Parent window changed - case XCB_REPARENT_NOTIFY: + case ReparentNotify: { - if (passEvent(windowEvent, reinterpret_cast<xcb_reparent_notify_event_t*>(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<xEvent*>(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<const uint8_t*>(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<xEvent*>(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 +1979,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<WindowImplX11*>::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 2e31fbf..a717bfb 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<xcb_generic_event_t*> 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 |