summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Cowgill <james410@cowgill.org.uk>2015-09-12 23:55:16 +0100
committerJames Cowgill <james410@cowgill.org.uk>2015-09-12 23:55:16 +0100
commit921ad626b5cd364b1b1e5bf45f68f09a55fd6e29 (patch)
treead819febfd6db600f4ee51e8af2f88a96daae745
parenta4e819b86ac71d1ac1c399260ff14c924281736d (diff)
parent301fd78b3ac87cf1fbce9d2c955db89094a304a5 (diff)
Merge tag 'upstream/2.3.2+dfsg'
Upstream version 2.3.2+dfsg # gpg: Signature made Sat 12 Sep 2015 23:55:03 BST using RSA key ID EA2D01EF # gpg: Good signature from "James Cowgill <james410@cowgill.org.uk>" # gpg: aka "James Cowgill <jc1311@york.ac.uk>" # gpg: aka "James Cowgill (Imagination Technologies) <James.Cowgill@imgtec.com>"
-rw-r--r--CMakeLists.txt2
-rw-r--r--CONTRIBUTING16
-rw-r--r--changelog.txt35
-rw-r--r--cmake/Modules/FindSFML.cmake6
-rw-r--r--include/SFML/Config.hpp2
-rw-r--r--include/SFML/Graphics/Font.hpp2
-rw-r--r--include/SFML/Graphics/Texture.hpp1
-rw-r--r--src/SFML/Audio/ALCheck.cpp23
-rw-r--r--src/SFML/Audio/ALCheck.hpp12
-rw-r--r--src/SFML/Graphics/GLCheck.cpp28
-rw-r--r--src/SFML/Graphics/GLCheck.hpp11
-rw-r--r--src/SFML/Graphics/ImageLoader.cpp55
-rw-r--r--src/SFML/Graphics/RenderTarget.cpp15
-rw-r--r--src/SFML/Graphics/RenderTexture.cpp3
-rw-r--r--src/SFML/Graphics/RenderTextureImplFBO.cpp3
-rw-r--r--src/SFML/Graphics/Shader.cpp24
-rw-r--r--src/SFML/Graphics/Texture.cpp4
-rw-r--r--src/SFML/Window/Unix/Display.cpp187
-rw-r--r--src/SFML/Window/Unix/Display.hpp17
-rw-r--r--src/SFML/Window/Unix/InputImpl.cpp253
-rw-r--r--src/SFML/Window/Unix/InputImpl.hpp6
-rw-r--r--src/SFML/Window/Unix/WindowImplX11.cpp716
-rw-r--r--src/SFML/Window/Unix/WindowImplX11.hpp14
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