From 608b4fb28d68ea9ba251f31965f533d082cdd816 Mon Sep 17 00:00:00 2001 From: Stefan Schindler Date: Fri, 8 May 2015 11:27:44 +0200 Subject: [PATCH 01/15] Only spawn Resized event when window size changes. --- src/SFML/Window/Unix/WindowImplX11.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index d8c26e065..9a1f4df67 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -1926,12 +1926,21 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) if (passEvent(windowEvent, reinterpret_cast(windowEvent)->window)) return false; + // X notifies about "window configuration events", which also includes moving a window only. Check + // for a different size and only spawn a Resized event when it differs. xcb_configure_notify_event_t* e = reinterpret_cast(windowEvent); - Event event; - event.type = Event::Resized; - event.size.width = e->width; - event.size.height = e->height; - pushEvent(event); + + if (e->width != m_previousSize.x || e->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; + pushEvent(event); + } break; } From 46a625dde5cdc24057133f61c7594a3dcaf405ea Mon Sep 17 00:00:00 2001 From: Tiaan Louw Date: Tue, 31 Mar 2015 21:42:04 +0200 Subject: [PATCH 02/15] Make sure the window still exists before we access the dimensions on it --- src/SFML/Main/MainAndroid.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/SFML/Main/MainAndroid.cpp b/src/SFML/Main/MainAndroid.cpp index 206940251..f6e2849e2 100644 --- a/src/SFML/Main/MainAndroid.cpp +++ b/src/SFML/Main/MainAndroid.cpp @@ -386,13 +386,16 @@ static void onContentRectChanged(ANativeActivity* activity, const ARect* rect) sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); sf::Lock lock(states->mutex); - // Send an event to warn people about the window move/resize - sf::Event event; - event.type = sf::Event::Resized; - event.size.width = ANativeWindow_getWidth(states->window); - event.size.height = ANativeWindow_getHeight(states->window); + // Make sure the window still exists before we access the dimensions on it + if (states->window != NULL) { + // Send an event to warn people about the window move/resize + sf::Event event; + event.type = sf::Event::Resized; + event.size.width = ANativeWindow_getWidth(states->window); + event.size.height = ANativeWindow_getHeight(states->window); - states->forwardEvent(event); + states->forwardEvent(event); + } } From d2adccfe2ea7a82bcfeccdbe4e0100704027df76 Mon Sep 17 00:00:00 2001 From: Tiaan Louw Date: Tue, 31 Mar 2015 23:27:59 +0200 Subject: [PATCH 03/15] Check Android API level We check the API level before using constants that use API levels that your device doesn't support. --- src/SFML/Main/MainAndroid.cpp | 56 ++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/src/SFML/Main/MainAndroid.cpp b/src/SFML/Main/MainAndroid.cpp index f6e2849e2..52e3816a1 100644 --- a/src/SFML/Main/MainAndroid.cpp +++ b/src/SFML/Main/MainAndroid.cpp @@ -53,6 +53,27 @@ namespace sf { namespace priv { + +//////////////////////////////////////////////////////////// +int getAndroidApiLevel(ANativeActivity* activity) +{ + JNIEnv* lJNIEnv = activity->env; + + jclass versionClass = lJNIEnv->FindClass("android/os/Build$VERSION"); + if (versionClass == NULL) + return 0; + + jfieldID sdkIntFieldID = lJNIEnv->GetStaticFieldID(versionClass, "SDK_INT", "I"); + if (sdkIntFieldID == NULL) + return 0; + + jint sdkInt = 0; + sdkInt = lJNIEnv->GetStaticIntField(versionClass, sdkIntFieldID); + + return sdkInt; +} + + //////////////////////////////////////////////////////////// ActivityStates* retrieveStates(ANativeActivity* activity) { @@ -117,6 +138,9 @@ void* main(ActivityStates* states) //////////////////////////////////////////////////////////// void goToFullscreenMode(ANativeActivity* activity) { + // Get the current Android API level. + int apiLevel = sf::priv::getAndroidApiLevel(activity); + // Hide the status bar ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_FULLSCREEN, AWINDOW_FLAG_FULLSCREEN); @@ -137,17 +161,35 @@ void goToFullscreenMode(ANativeActivity* activity) jclass classView = lJNIEnv->FindClass("android/view/View"); - jfieldID FieldSYSTEM_UI_FLAG_LOW_PROFILE = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_LOW_PROFILE", "I"); - jint SYSTEM_UI_FLAG_LOW_PROFILE = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_LOW_PROFILE); + // Default flags + jint flags = 0; + + // API Level 14 + if (apiLevel >= 14) + { + jfieldID FieldSYSTEM_UI_FLAG_LOW_PROFILE = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_LOW_PROFILE", "I"); + jint SYSTEM_UI_FLAG_LOW_PROFILE = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_LOW_PROFILE); + flags |= SYSTEM_UI_FLAG_LOW_PROFILE; + } - jfieldID FieldSYSTEM_UI_FLAG_FULLSCREEN = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_FULLSCREEN", "I"); - jint SYSTEM_UI_FLAG_FULLSCREEN = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_FULLSCREEN); + // API Level 16 + if (apiLevel >= 16) + { + jfieldID FieldSYSTEM_UI_FLAG_FULLSCREEN = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_FULLSCREEN", "I"); + jint SYSTEM_UI_FLAG_FULLSCREEN = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_FULLSCREEN); + flags |= SYSTEM_UI_FLAG_FULLSCREEN; + } - //jfieldID FieldSYSTEM_UI_FLAG_IMMERSIVE_STICKY = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_IMMERSIVE_STICKY", "I"); - //jint SYSTEM_UI_FLAG_IMMERSIVE_STICKY = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_IMMERSIVE_STICKY); + // API Level 19 + if (apiLevel >= 19) + { + jfieldID FieldSYSTEM_UI_FLAG_IMMERSIVE_STICKY = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_IMMERSIVE_STICKY", "I"); + jint SYSTEM_UI_FLAG_IMMERSIVE_STICKY = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_IMMERSIVE_STICKY); + flags |= SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + } jmethodID methodsetSystemUiVisibility = lJNIEnv->GetMethodID(classView, "setSystemUiVisibility", "(I)V"); - lJNIEnv->CallVoidMethod(objectDecorView, methodsetSystemUiVisibility, SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_FULLSCREEN | 0x00001000); + lJNIEnv->CallVoidMethod(objectDecorView, methodsetSystemUiVisibility, flags); } //////////////////////////////////////////////////////////// From e38a26ec25bc3540eb6745a99d8db55a185e317c Mon Sep 17 00:00:00 2001 From: binary1248 Date: Mon, 11 May 2015 00:38:14 +0200 Subject: [PATCH 04/15] Corrected typo. --- src/SFML/Window/Unix/Display.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SFML/Window/Unix/Display.hpp b/src/SFML/Window/Unix/Display.hpp index 1cda4a7ed..bddd9a7be 100644 --- a/src/SFML/Window/Unix/Display.hpp +++ b/src/SFML/Window/Unix/Display.hpp @@ -51,7 +51,7 @@ Display* OpenDisplay(); /// \brief Get the xcb connection of the shared Display /// /// This function increments the reference count of the display, -/// it must be matched with a call to CloseDisplay. +/// it must be matched with a call to CloseConnection. /// /// \return Pointer to the shared connection /// From 45577de60a172cd1c92a278320688736134a0ed1 Mon Sep 17 00:00:00 2001 From: binary1248 Date: Sun, 10 May 2015 17:04:01 +0200 Subject: [PATCH 05/15] Added support for GL_EXT_texture_edge_clamp as well since some GL implementations don't expose GL_SGIS_texture_edge_clamp even when clamp-to-edge functionality is supported. Fixes #880 --- src/SFML/Graphics/GLExtensions.hpp | 4 ++++ src/SFML/Graphics/GLExtensions.txt | 1 + src/SFML/Graphics/GLLoader.cpp | 7 +++++-- src/SFML/Graphics/GLLoader.hpp | 3 +++ src/SFML/Graphics/Texture.cpp | 16 ++++++++++------ 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/SFML/Graphics/GLExtensions.hpp b/src/SFML/Graphics/GLExtensions.hpp index 7cff5947f..52195a195 100644 --- a/src/SFML/Graphics/GLExtensions.hpp +++ b/src/SFML/Graphics/GLExtensions.hpp @@ -45,6 +45,7 @@ // Core since 1.0 #define GLEXT_multitexture true #define GLEXT_texture_edge_clamp true + #define GLEXT_EXT_texture_edge_clamp true #define GLEXT_blend_minmax true #define GLEXT_glClientActiveTexture glClientActiveTexture #define GLEXT_glActiveTexture glActiveTexture @@ -130,6 +131,9 @@ #define GLEXT_texture_edge_clamp sfogl_ext_SGIS_texture_edge_clamp #define GLEXT_GL_CLAMP_TO_EDGE GL_CLAMP_TO_EDGE_SGIS + // Core since 1.2 - EXT_texture_edge_clamp + #define GLEXT_EXT_texture_edge_clamp sfogl_ext_EXT_texture_edge_clamp + // Core since 1.2 - EXT_blend_minmax #define GLEXT_blend_minmax sfogl_ext_EXT_blend_minmax #define GLEXT_glBlendEquation glBlendEquationEXT diff --git a/src/SFML/Graphics/GLExtensions.txt b/src/SFML/Graphics/GLExtensions.txt index 5f2b5b338..033404d2d 100644 --- a/src/SFML/Graphics/GLExtensions.txt +++ b/src/SFML/Graphics/GLExtensions.txt @@ -4,6 +4,7 @@ // lua LoadGen.lua -style=pointer_c -spec=gl -version=1.1 -indent=space -prefix=sf -extfile=GLExtensions.txt GLLoader SGIS_texture_edge_clamp +//EXT_texture_edge_clamp EXT_blend_minmax EXT_blend_subtract ARB_multitexture diff --git a/src/SFML/Graphics/GLLoader.cpp b/src/SFML/Graphics/GLLoader.cpp index cceab2f4a..e82cd7a2c 100644 --- a/src/SFML/Graphics/GLLoader.cpp +++ b/src/SFML/Graphics/GLLoader.cpp @@ -50,6 +50,7 @@ static sf::GlFunctionPointer IntGetProcAddress(const char* name) } int sfogl_ext_SGIS_texture_edge_clamp = sfogl_LOAD_FAILED; +int sfogl_ext_EXT_texture_edge_clamp = sfogl_LOAD_FAILED; int sfogl_ext_EXT_blend_minmax = sfogl_LOAD_FAILED; int sfogl_ext_EXT_blend_subtract = sfogl_LOAD_FAILED; int sfogl_ext_ARB_multitexture = sfogl_LOAD_FAILED; @@ -317,8 +318,9 @@ typedef struct sfogl_StrToExtMap_s PFN_LOADFUNCPOINTERS LoadExtension; } sfogl_StrToExtMap; -static sfogl_StrToExtMap ExtensionMap[12] = { +static sfogl_StrToExtMap ExtensionMap[13] = { {"GL_SGIS_texture_edge_clamp", &sfogl_ext_SGIS_texture_edge_clamp, NULL}, + {"GL_EXT_texture_edge_clamp", &sfogl_ext_EXT_texture_edge_clamp, NULL}, {"GL_EXT_blend_minmax", &sfogl_ext_EXT_blend_minmax, Load_EXT_blend_minmax}, {"GL_EXT_blend_subtract", &sfogl_ext_EXT_blend_subtract, NULL}, {"GL_ARB_multitexture", &sfogl_ext_ARB_multitexture, Load_ARB_multitexture}, @@ -332,7 +334,7 @@ static sfogl_StrToExtMap ExtensionMap[12] = { {"GL_EXT_framebuffer_object", &sfogl_ext_EXT_framebuffer_object, Load_EXT_framebuffer_object} }; -static int g_extensionMapSize = 12; +static int g_extensionMapSize = 13; static sfogl_StrToExtMap *FindExtEntry(const char *extensionName) { @@ -350,6 +352,7 @@ static sfogl_StrToExtMap *FindExtEntry(const char *extensionName) static void ClearExtensionVars() { sfogl_ext_SGIS_texture_edge_clamp = sfogl_LOAD_FAILED; + sfogl_ext_EXT_texture_edge_clamp = sfogl_LOAD_FAILED; sfogl_ext_EXT_blend_minmax = sfogl_LOAD_FAILED; sfogl_ext_EXT_blend_subtract = sfogl_LOAD_FAILED; sfogl_ext_ARB_multitexture = sfogl_LOAD_FAILED; diff --git a/src/SFML/Graphics/GLLoader.hpp b/src/SFML/Graphics/GLLoader.hpp index 42e1e093a..000640659 100644 --- a/src/SFML/Graphics/GLLoader.hpp +++ b/src/SFML/Graphics/GLLoader.hpp @@ -174,6 +174,7 @@ extern "C" { #endif /*__cplusplus*/ extern int sfogl_ext_SGIS_texture_edge_clamp; +extern int sfogl_ext_EXT_texture_edge_clamp; extern int sfogl_ext_EXT_blend_minmax; extern int sfogl_ext_EXT_blend_subtract; extern int sfogl_ext_ARB_multitexture; @@ -188,6 +189,8 @@ extern int sfogl_ext_EXT_framebuffer_object; #define GL_CLAMP_TO_EDGE_SGIS 0x812F +#define GL_CLAMP_TO_EDGE_EXT 0x812F + #define GL_BLEND_EQUATION_EXT 0x8009 #define GL_FUNC_ADD_EXT 0x8006 #define GL_MAX_EXT 0x8008 diff --git a/src/SFML/Graphics/Texture.cpp b/src/SFML/Graphics/Texture.cpp index a747a2db2..610dfa2cd 100644 --- a/src/SFML/Graphics/Texture.cpp +++ b/src/SFML/Graphics/Texture.cpp @@ -158,7 +158,9 @@ bool Texture::create(unsigned int width, unsigned int height) // Make sure that the current texture binding will be preserved priv::TextureSaver save; - if (!m_isRepeated && !GLEXT_texture_edge_clamp) + static bool textureEdgeClamp = GLEXT_texture_edge_clamp || GLEXT_EXT_texture_edge_clamp; + + if (!m_isRepeated && !textureEdgeClamp) { static bool warned = false; @@ -175,8 +177,8 @@ bool Texture::create(unsigned int width, unsigned int height) // Initialize the texture glCheck(glBindTexture(GL_TEXTURE_2D, m_texture)); glCheck(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_actualSize.x, m_actualSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL)); - glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_isRepeated ? GL_REPEAT : (GLEXT_texture_edge_clamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP))); - glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_isRepeated ? GL_REPEAT : (GLEXT_texture_edge_clamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP))); + glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_isRepeated ? GL_REPEAT : (textureEdgeClamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP))); + glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_isRepeated ? GL_REPEAT : (textureEdgeClamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP))); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST)); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST)); m_cacheId = getUniqueId(); @@ -480,7 +482,9 @@ void Texture::setRepeated(bool repeated) // Make sure that the current texture binding will be preserved priv::TextureSaver save; - if (!m_isRepeated && !GLEXT_texture_edge_clamp) + static bool textureEdgeClamp = GLEXT_texture_edge_clamp || GLEXT_EXT_texture_edge_clamp; + + if (!m_isRepeated && !textureEdgeClamp) { static bool warned = false; @@ -495,8 +499,8 @@ void Texture::setRepeated(bool repeated) } glCheck(glBindTexture(GL_TEXTURE_2D, m_texture)); - glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_isRepeated ? GL_REPEAT : (GLEXT_texture_edge_clamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP))); - glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_isRepeated ? GL_REPEAT : (GLEXT_texture_edge_clamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP))); + glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_isRepeated ? GL_REPEAT : (textureEdgeClamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP))); + glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_isRepeated ? GL_REPEAT : (textureEdgeClamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP))); } } } From 11e2901403116c4ab24cf7acc104111eccca8890 Mon Sep 17 00:00:00 2001 From: binary1248 Date: Sun, 10 May 2015 03:46:17 +0200 Subject: [PATCH 06/15] Whitelisted SHAPE events that might be sent by some compositing window managers even if we didn't select them. Fixes #879 --- src/SFML/Window/Unix/WindowImplX11.cpp | 28 ++++++++++++++++---------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 9a1f4df67..07f27a854 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -237,21 +237,17 @@ namespace return true; } - xcb_query_extension_reply_t getDriExtension() + xcb_query_extension_reply_t getXExtension(const std::string& name) { xcb_connection_t* connection = sf::priv::OpenConnection(); sf::priv::ScopedXcbPtr error(NULL); - - // Check if the DRI2 extension is present - // We don't use xcb_get_extension_data here to avoid having to link to xcb_dri2 - static const std::string DRI2 = "DRI2"; - sf::priv::ScopedXcbPtr driExt(xcb_query_extension_reply( + sf::priv::ScopedXcbPtr extension(xcb_query_extension_reply( connection, xcb_query_extension( connection, - DRI2.size(), - DRI2.c_str() + name.size(), + name.c_str() ), &error )); @@ -259,14 +255,14 @@ namespace // Close the connection with the X server sf::priv::CloseConnection(connection); - if (error || !driExt || !driExt->present) + if (error || !extension || !extension->present) { xcb_query_extension_reply_t reply; std::memset(&reply, 0, sizeof(reply)); return reply; } - return *driExt.get(); + return *extension.get(); } void dumpXcbExtensions() @@ -2260,8 +2256,18 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) // 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 = getDriExtension(); + 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 From 717bd85537d734700edae7198b3d0fcfaf3ca82a Mon Sep 17 00:00:00 2001 From: Mario Liebisch Date: Tue, 12 May 2015 10:40:29 +0200 Subject: [PATCH 07/15] Android: Fixed audio files not loading (and possibly crashing) * Added a missing return value for Android's `sf::FileInputStream::open()`. * Added a missing return value for Android's `sf::priv::ResourceStream::seek()`. * Moved error logging for `sf::InputSoundFile` and `sf::OutputSoundFile` to `sf::SoundFileFactory`, since this allows more details on *why* reading/writing failed. Before missing files would return "format not supported". --- src/SFML/Audio/InputSoundFile.cpp | 9 --------- src/SFML/Audio/OutputSoundFile.cpp | 4 ---- src/SFML/Audio/SoundFileFactory.cpp | 9 ++++++++- src/SFML/System/Android/ResourceStream.cpp | 2 +- src/SFML/System/FileInputStream.cpp | 1 + 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/SFML/Audio/InputSoundFile.cpp b/src/SFML/Audio/InputSoundFile.cpp index 2f281f569..ede0f478e 100644 --- a/src/SFML/Audio/InputSoundFile.cpp +++ b/src/SFML/Audio/InputSoundFile.cpp @@ -65,10 +65,7 @@ bool InputSoundFile::openFromFile(const std::string& filename) // Find a suitable reader for the file type m_reader = SoundFileFactory::createReaderFromFilename(filename); if (!m_reader) - { - err() << "Failed to open sound file \"" << filename << "\" (format not supported)" << std::endl; return false; - } // Wrap the file into a stream FileInputStream* file = new FileInputStream; @@ -108,10 +105,7 @@ bool InputSoundFile::openFromMemory(const void* data, std::size_t sizeInBytes) // Find a suitable reader for the file type m_reader = SoundFileFactory::createReaderFromMemory(data, sizeInBytes); if (!m_reader) - { - err() << "Failed to open sound file from memory (format not supported)" << std::endl; return false; - } // Wrap the memory file into a stream MemoryInputStream* memory = new MemoryInputStream; @@ -147,10 +141,7 @@ bool InputSoundFile::openFromStream(InputStream& stream) // Find a suitable reader for the file type m_reader = SoundFileFactory::createReaderFromStream(stream); if (!m_reader) - { - err() << "Failed to open sound file from stream (format not supported)" << std::endl; return false; - } // store the stream m_stream = &stream; diff --git a/src/SFML/Audio/OutputSoundFile.cpp b/src/SFML/Audio/OutputSoundFile.cpp index 5bb0e2405..8f43ca762 100644 --- a/src/SFML/Audio/OutputSoundFile.cpp +++ b/src/SFML/Audio/OutputSoundFile.cpp @@ -28,7 +28,6 @@ #include #include #include -#include namespace sf @@ -57,10 +56,7 @@ bool OutputSoundFile::openFromFile(const std::string& filename, unsigned int sam // Find a suitable writer for the file type m_writer = SoundFileFactory::createWriterFromFilename(filename); if (!m_writer) - { - err() << "Failed to open sound file \"" << filename << "\" (format not supported)" << std::endl; return false; - } // Pass the stream to the reader if (!m_writer->open(filename, sampleRate, channelCount)) diff --git a/src/SFML/Audio/SoundFileFactory.cpp b/src/SFML/Audio/SoundFileFactory.cpp index 02d4c99c8..fa2811c86 100644 --- a/src/SFML/Audio/SoundFileFactory.cpp +++ b/src/SFML/Audio/SoundFileFactory.cpp @@ -34,6 +34,7 @@ #include #include #include +#include namespace @@ -69,8 +70,10 @@ SoundFileReader* SoundFileFactory::createReaderFromFilename(const std::string& f // Wrap the input file into a file stream FileInputStream stream; - if (!stream.open(filename)) + if (!stream.open(filename)) { + err() << "Failed to open sound file \"" << filename << "\" (couldn't open stream)" << std::endl; return NULL; + } // Test the filename in all the registered factories for (ReaderFactoryArray::const_iterator it = s_readers.begin(); it != s_readers.end(); ++it) @@ -81,6 +84,7 @@ SoundFileReader* SoundFileFactory::createReaderFromFilename(const std::string& f } // No suitable reader found + err() << "Failed to open sound file \"" << filename << "\" (format not supported)" << std::endl; return NULL; } @@ -104,6 +108,7 @@ SoundFileReader* SoundFileFactory::createReaderFromMemory(const void* data, std: } // No suitable reader found + err() << "Failed to open sound file from memory (format not supported)" << std::endl; return NULL; } @@ -123,6 +128,7 @@ SoundFileReader* SoundFileFactory::createReaderFromStream(InputStream& stream) } // No suitable reader found + err() << "Failed to open sound file from stream (format not supported)" << std::endl; return NULL; } @@ -141,6 +147,7 @@ SoundFileWriter* SoundFileFactory::createWriterFromFilename(const std::string& f } // No suitable writer found + err() << "Failed to open sound file \"" << filename << "\" (format not supported)" << std::endl; return NULL; } diff --git a/src/SFML/System/Android/ResourceStream.cpp b/src/SFML/System/Android/ResourceStream.cpp index abfa29e6e..fbc1ec4fa 100644 --- a/src/SFML/System/Android/ResourceStream.cpp +++ b/src/SFML/System/Android/ResourceStream.cpp @@ -63,7 +63,7 @@ Int64 ResourceStream::read(void *data, Int64 size) //////////////////////////////////////////////////////////// Int64 ResourceStream::seek(Int64 position) { - AAsset_seek(m_file, position, SEEK_SET); + return AAsset_seek(m_file, position, SEEK_SET); } diff --git a/src/SFML/System/FileInputStream.cpp b/src/SFML/System/FileInputStream.cpp index dee021f24..bea0461d5 100644 --- a/src/SFML/System/FileInputStream.cpp +++ b/src/SFML/System/FileInputStream.cpp @@ -61,6 +61,7 @@ bool FileInputStream::open(const std::string& filename) if (m_file) delete m_file; m_file = new sf::priv::ResourceStream(filename); + return m_file->tell() != -1; #else if (m_file) std::fclose(m_file); From 1b1d92d6bba9894a89433f625d169abe5a3df996 Mon Sep 17 00:00:00 2001 From: Juhani Numminen Date: Sat, 16 May 2015 08:52:10 +0300 Subject: [PATCH 08/15] Fix function name in short example snippet in RenderStates.hpp --- include/SFML/Graphics/RenderStates.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/SFML/Graphics/RenderStates.hpp b/include/SFML/Graphics/RenderStates.hpp index b23a778e1..3ab3271f4 100644 --- a/include/SFML/Graphics/RenderStates.hpp +++ b/include/SFML/Graphics/RenderStates.hpp @@ -150,7 +150,7 @@ public: /// directly without defining render states explicitly -- the /// default set of states is ok in most cases. /// \code -/// window.Draw(sprite); +/// window.draw(sprite); /// \endcode /// /// If you want to use a single specific render state, From 6cec9723387ff2c87f2109aa9cc5da53eb977fbd Mon Sep 17 00:00:00 2001 From: Jan Haller Date: Wed, 20 May 2015 17:26:26 +0200 Subject: [PATCH 09/15] Removed unnecessary sf:: prefixes --- include/SFML/Audio/SoundRecorder.hpp | 4 ++-- include/SFML/Graphics/Font.hpp | 2 +- include/SFML/Graphics/Shader.hpp | 2 +- include/SFML/Graphics/Texture.hpp | 2 +- include/SFML/System/FileInputStream.hpp | 2 +- include/SFML/Window/Joystick.hpp | 2 +- src/SFML/Audio/SoundRecorder.cpp | 4 ++-- src/SFML/Graphics/Shader.cpp | 4 ++-- src/SFML/Graphics/Shape.cpp | 2 +- src/SFML/Network/TcpSocket.cpp | 2 +- src/SFML/System/FileInputStream.cpp | 6 +++--- 11 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/SFML/Audio/SoundRecorder.hpp b/include/SFML/Audio/SoundRecorder.hpp index ab0eb24e3..964e4f3fc 100644 --- a/include/SFML/Audio/SoundRecorder.hpp +++ b/include/SFML/Audio/SoundRecorder.hpp @@ -183,7 +183,7 @@ protected: /// \param interval Processing interval /// //////////////////////////////////////////////////////////// - void setProcessingInterval(sf::Time interval); + void setProcessingInterval(Time interval); //////////////////////////////////////////////////////////// /// \brief Start capturing audio data @@ -260,7 +260,7 @@ private: Thread m_thread; ///< Thread running the background recording task std::vector m_samples; ///< Buffer to store captured samples unsigned int m_sampleRate; ///< Sample rate - sf::Time m_processingInterval; ///< Time period between calls to onProcessSamples + Time m_processingInterval; ///< Time period between calls to onProcessSamples bool m_isCapturing; ///< Capturing state std::string m_deviceName; ///< Name of the audio capture device }; diff --git a/include/SFML/Graphics/Font.hpp b/include/SFML/Graphics/Font.hpp index 84eee27fe..9d7c68417 100644 --- a/include/SFML/Graphics/Font.hpp +++ b/include/SFML/Graphics/Font.hpp @@ -278,7 +278,7 @@ private: Page(); GlyphTable glyphs; ///< Table mapping code points to their corresponding glyph - sf::Texture texture; ///< Texture containing the pixels of the glyphs + Texture texture; ///< Texture containing the pixels of the glyphs unsigned int nextRow; ///< Y position of the next new row in the texture std::vector rows; ///< List containing the position of all the existing rows }; diff --git a/include/SFML/Graphics/Shader.hpp b/include/SFML/Graphics/Shader.hpp index d3278f9b5..55cc3bb73 100644 --- a/include/SFML/Graphics/Shader.hpp +++ b/include/SFML/Graphics/Shader.hpp @@ -399,7 +399,7 @@ public: /// \param transform Transform to assign /// //////////////////////////////////////////////////////////// - void setParameter(const std::string& name, const sf::Transform& transform); + void setParameter(const std::string& name, const Transform& transform); //////////////////////////////////////////////////////////// /// \brief Change a texture parameter of the shader diff --git a/include/SFML/Graphics/Texture.hpp b/include/SFML/Graphics/Texture.hpp index 421861e09..29260d18b 100644 --- a/include/SFML/Graphics/Texture.hpp +++ b/include/SFML/Graphics/Texture.hpp @@ -187,7 +187,7 @@ public: /// \see loadFromFile, loadFromMemory, loadFromImage /// //////////////////////////////////////////////////////////// - bool loadFromStream(sf::InputStream& stream, const IntRect& area = IntRect()); + bool loadFromStream(InputStream& stream, const IntRect& area = IntRect()); //////////////////////////////////////////////////////////// /// \brief Load the texture from an image diff --git a/include/SFML/System/FileInputStream.hpp b/include/SFML/System/FileInputStream.hpp index 1afa93918..995351ca9 100644 --- a/include/SFML/System/FileInputStream.hpp +++ b/include/SFML/System/FileInputStream.hpp @@ -123,7 +123,7 @@ private: // Member data //////////////////////////////////////////////////////////// #ifdef ANDROID - sf::priv::ResourceStream *m_file; + priv::ResourceStream* m_file; #else std::FILE* m_file; ///< stdio file stream #endif diff --git a/include/SFML/Window/Joystick.hpp b/include/SFML/Window/Joystick.hpp index 185fd76f7..27f6291e2 100644 --- a/include/SFML/Window/Joystick.hpp +++ b/include/SFML/Window/Joystick.hpp @@ -77,7 +77,7 @@ public: { Identification(); - sf::String name; ///< Name of the joystick + String name; ///< Name of the joystick unsigned int vendorId; ///< Manufacturer identifier unsigned int productId; ///< Product identifier }; diff --git a/src/SFML/Audio/SoundRecorder.cpp b/src/SFML/Audio/SoundRecorder.cpp index 84a48545a..f051b963a 100644 --- a/src/SFML/Audio/SoundRecorder.cpp +++ b/src/SFML/Audio/SoundRecorder.cpp @@ -135,7 +135,7 @@ std::vector SoundRecorder::getAvailableDevices() { std::vector deviceNameList; - const ALchar *deviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); + const ALchar* deviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); if (deviceList) { while (*deviceList) @@ -210,7 +210,7 @@ bool SoundRecorder::isAvailable() //////////////////////////////////////////////////////////// -void SoundRecorder::setProcessingInterval(sf::Time interval) +void SoundRecorder::setProcessingInterval(Time interval) { m_processingInterval = interval; } diff --git a/src/SFML/Graphics/Shader.cpp b/src/SFML/Graphics/Shader.cpp index 80ca28e1d..5d87d10de 100644 --- a/src/SFML/Graphics/Shader.cpp +++ b/src/SFML/Graphics/Shader.cpp @@ -385,7 +385,7 @@ void Shader::setParameter(const std::string& name, const Color& color) //////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, const sf::Transform& transform) +void Shader::setParameter(const std::string& name, const Transform& transform) { if (m_shaderProgram) { @@ -768,7 +768,7 @@ void Shader::setParameter(const std::string& name, const Color& color) //////////////////////////////////////////////////////////// -void Shader::setParameter(const std::string& name, const sf::Transform& transform) +void Shader::setParameter(const std::string& name, const Transform& transform) { } diff --git a/src/SFML/Graphics/Shape.cpp b/src/SFML/Graphics/Shape.cpp index 3487777d4..5403b4048 100644 --- a/src/SFML/Graphics/Shape.cpp +++ b/src/SFML/Graphics/Shape.cpp @@ -66,7 +66,7 @@ void Shape::setTexture(const Texture* texture, bool resetRect) if (texture) { // Recompute the texture area if requested, or if there was no texture & rect before - if (resetRect || (!m_texture && (m_textureRect == sf::IntRect()))) + if (resetRect || (!m_texture && (m_textureRect == IntRect()))) setTextureRect(IntRect(0, 0, texture->getSize().x, texture->getSize().y)); } diff --git a/src/SFML/Network/TcpSocket.cpp b/src/SFML/Network/TcpSocket.cpp index 5a032efcd..6476c5344 100644 --- a/src/SFML/Network/TcpSocket.cpp +++ b/src/SFML/Network/TcpSocket.cpp @@ -179,7 +179,7 @@ Socket::Status TcpSocket::connect(const IpAddress& remoteAddress, unsigned short { // At this point the connection may have been either accepted or refused. // To know whether it's a success or a failure, we must check the address of the connected peer - if (getRemoteAddress() != sf::IpAddress::None) + if (getRemoteAddress() != IpAddress::None) { // Connection accepted status = Done; diff --git a/src/SFML/System/FileInputStream.cpp b/src/SFML/System/FileInputStream.cpp index bea0461d5..82f4d72c9 100644 --- a/src/SFML/System/FileInputStream.cpp +++ b/src/SFML/System/FileInputStream.cpp @@ -60,7 +60,7 @@ bool FileInputStream::open(const std::string& filename) #ifdef ANDROID if (m_file) delete m_file; - m_file = new sf::priv::ResourceStream(filename); + m_file = new priv::ResourceStream(filename); return m_file->tell() != -1; #else if (m_file) @@ -128,9 +128,9 @@ Int64 FileInputStream::getSize() #else if (m_file) { - sf::Int64 position = tell(); + Int64 position = tell(); std::fseek(m_file, 0, SEEK_END); - sf::Int64 size = tell(); + Int64 size = tell(); seek(position); return size; } From 6de027f198e56947d89694049020de0893d374fc Mon Sep 17 00:00:00 2001 From: Jan Haller Date: Sat, 23 May 2015 15:15:14 +0200 Subject: [PATCH 10/15] Clarified lifetime requirements of underlying resources for Music and Font --- include/SFML/Audio/Music.hpp | 24 ++++++++++++++++-------- include/SFML/Graphics/Font.hpp | 14 ++++++++++++-- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/include/SFML/Audio/Music.hpp b/include/SFML/Audio/Music.hpp index a50272445..76b4254eb 100644 --- a/include/SFML/Audio/Music.hpp +++ b/include/SFML/Audio/Music.hpp @@ -69,6 +69,10 @@ public: /// See the documentation of sf::InputSoundFile for the list /// of supported formats. /// + /// \warning Since the music is not loaded at once but rather + /// streamed continuously, the file must remain accessible until + /// the sf::Music object loads a new music or is destroyed. + /// /// \param filename Path of the music file to open /// /// \return True if loading succeeded, false if it failed @@ -85,10 +89,11 @@ public: /// to do so). /// See the documentation of sf::InputSoundFile for the list /// of supported formats. - /// Since the music is not loaded completely but rather streamed - /// continuously, the \a data must remain available as long as the - /// music is playing (i.e. you can't deallocate it right after calling - /// this function). + /// + /// \warning Since the music is not loaded at once but rather streamed + /// continuously, the \a data buffer must remain accessible until + /// the sf::Music object loads a new music or is destroyed. That is, + /// you can't deallocate the buffer right after calling this function. /// /// \param data Pointer to the file data in memory /// \param sizeInBytes Size of the data to load, in bytes @@ -107,10 +112,10 @@ public: /// to do so). /// See the documentation of sf::InputSoundFile for the list /// of supported formats. - /// Since the music is not loaded completely but rather streamed - /// continuously, the \a stream must remain alive as long as the - /// music is playing (i.e. you can't destroy it right after calling - /// this function). + /// + /// \warning Since the music is not loaded at once but rather + /// streamed continuously, the \a stream must remain accessible + /// until the sf::Music object loads a new music or is destroyed. /// /// \param stream Source stream to read from /// @@ -184,6 +189,9 @@ private: /// musics that usually take hundreds of MB when they are /// uncompressed: by streaming it instead of loading it entirely, /// you avoid saturating the memory and have almost no loading delay. +/// This implies that the underlying resource (file, stream or +/// memory buffer) must remain valid for the lifetime of the +/// sf::Music object. /// /// Apart from that, a sf::Music has almost the same features as /// the sf::SoundBuffer / sf::Sound pair: you can play/pause/stop diff --git a/include/SFML/Graphics/Font.hpp b/include/SFML/Graphics/Font.hpp index 9d7c68417..2b19d3987 100644 --- a/include/SFML/Graphics/Font.hpp +++ b/include/SFML/Graphics/Font.hpp @@ -95,6 +95,10 @@ public: /// fonts installed on the user's system, thus you can't /// load them directly. /// + /// \warning SFML cannot preload all the font data in this + /// function, so the file has to remain accessible until + /// the sf::Font object loads a new font or is destroyed. + /// /// \param filename Path of the font file to load /// /// \return True if loading succeeded, false if it failed @@ -109,9 +113,11 @@ public: /// /// The supported font formats are: TrueType, Type 1, CFF, /// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. - /// Warning: SFML cannot preload all the font data in this + /// + /// \warning SFML cannot preload all the font data in this /// function, so the buffer pointed by \a data has to remain - /// valid as long as the font is used. + /// valid until the sf::Font object loads a new font or + /// is destroyed. /// /// \param data Pointer to the file data in memory /// \param sizeInBytes Size of the data to load, in bytes @@ -132,6 +138,10 @@ public: /// function, so the contents of \a stream have to remain /// valid as long as the font is used. /// + /// \warning SFML cannot preload all the font data in this + /// function, so the stream has to remain accessible until + /// the sf::Font object loads a new font or is destroyed. + /// /// \param stream Source stream to read from /// /// \return True if loading succeeded, false if it failed From 0df1c97af741bd1659780ce8c150ed8d357e9a4e Mon Sep 17 00:00:00 2001 From: binary1248 Date: Sat, 23 May 2015 19:32:41 +0200 Subject: [PATCH 11/15] Fixed keyboard mapping not being correct after the user changes their keyboard layout while an SFML application is running. Fixes #895 --- src/SFML/Window/Unix/Display.cpp | 146 ++++++++--------- src/SFML/Window/Unix/Display.hpp | 6 + src/SFML/Window/Unix/InputImpl.cpp | 216 +++++++++++++------------ src/SFML/Window/Unix/InputImpl.hpp | 6 + src/SFML/Window/Unix/WindowImplX11.cpp | 56 +++++++ 5 files changed, 251 insertions(+), 179 deletions(-) diff --git a/src/SFML/Window/Unix/Display.cpp b/src/SFML/Window/Unix/Display.cpp index e537224cd..cf1357db1 100644 --- a/src/SFML/Window/Unix/Display.cpp +++ b/src/SFML/Window/Unix/Display.cpp @@ -145,77 +145,6 @@ namespace return keysym; } - - void buildMap() - { - // Open a connection with the X server - xcb_connection_t* connection = sf::priv::OpenConnection(); - - firstKeycode = xcb_get_setup(connection)->min_keycode; - lastKeycode = xcb_get_setup(connection)->max_keycode; - - sf::priv::ScopedXcbPtr error(NULL); - - sf::priv::ScopedXcbPtr keyboardMapping(xcb_get_keyboard_mapping_reply( - connection, - xcb_get_keyboard_mapping( - connection, - firstKeycode, - lastKeycode - firstKeycode + 1 - ), - &error - )); - - sf::priv::CloseConnection(connection); - - if (error || !keyboardMapping) - { - sf::err() << "Failed to get keyboard mapping" << std::endl; - return; - } - - uint8_t keysymsPerKeycode = keyboardMapping->keysyms_per_keycode; - - if (!keysymsPerKeycode) - { - sf::err() << "Error: No keysyms per keycode" << std::endl; - return; - } - - const xcb_keysym_t* keysyms = xcb_get_keyboard_mapping_keysyms(keyboardMapping.get()); - - if (!keysyms) - { - sf::err() << "Failed to get keyboard mapping keysyms" << std::endl; - return; - } - - xcb_keycode_t range = lastKeycode - firstKeycode + 1; - - std::fill(keysymMap, keysymMap + 256, XK_VoidSymbol); - - for (xcb_keycode_t i = firstKeycode; ; ++i) - { - const xcb_keysym_t* keysym = &keysyms[(i - firstKeycode) * keysymsPerKeycode]; - - if ((keysymsPerKeycode == 1) || (keysym[1] == XCB_NO_SYMBOL)) - { - keysymMap[i] = keysymToLower(keysym[0]); - - if (i == lastKeycode) - break; - - continue; - } - - keysymMap[i] = keysym[0]; - - if (i == lastKeycode) - break; - } - - mapBuilt = true; - } } namespace sf @@ -344,11 +273,84 @@ xcb_atom_t getAtom(const std::string& name, bool onlyIfExists) const xcb_keysym_t* getKeysymMap() { if (!mapBuilt) - buildMap(); + buildKeysymMap(); return keysymMap; } + +//////////////////////////////////////////////////////////// +void buildKeysymMap() +{ + // Open a connection with the X server + xcb_connection_t* connection = sf::priv::OpenConnection(); + + firstKeycode = xcb_get_setup(connection)->min_keycode; + lastKeycode = xcb_get_setup(connection)->max_keycode; + + sf::priv::ScopedXcbPtr error(NULL); + + sf::priv::ScopedXcbPtr keyboardMapping(xcb_get_keyboard_mapping_reply( + connection, + xcb_get_keyboard_mapping( + connection, + firstKeycode, + lastKeycode - firstKeycode + 1 + ), + &error + )); + + sf::priv::CloseConnection(connection); + + if (error || !keyboardMapping) + { + sf::err() << "Failed to get keyboard mapping" << std::endl; + return; + } + + uint8_t keysymsPerKeycode = keyboardMapping->keysyms_per_keycode; + + if (!keysymsPerKeycode) + { + sf::err() << "Error: No keysyms per keycode" << std::endl; + return; + } + + const xcb_keysym_t* keysyms = xcb_get_keyboard_mapping_keysyms(keyboardMapping.get()); + + if (!keysyms) + { + sf::err() << "Failed to get keyboard mapping keysyms" << std::endl; + return; + } + + xcb_keycode_t range = lastKeycode - firstKeycode + 1; + + std::fill(keysymMap, keysymMap + 256, XK_VoidSymbol); + + for (xcb_keycode_t i = firstKeycode; ; ++i) + { + const xcb_keysym_t* keysym = &keysyms[(i - firstKeycode) * keysymsPerKeycode]; + + if ((keysymsPerKeycode == 1) || (keysym[1] == XCB_NO_SYMBOL)) + { + keysymMap[i] = keysymToLower(keysym[0]); + + if (i == lastKeycode) + break; + + continue; + } + + keysymMap[i] = keysym[0]; + + if (i == lastKeycode) + break; + } + + mapBuilt = true; +} + } // namespace priv } // namespace sf diff --git a/src/SFML/Window/Unix/Display.hpp b/src/SFML/Window/Unix/Display.hpp index bddd9a7be..da29d5102 100644 --- a/src/SFML/Window/Unix/Display.hpp +++ b/src/SFML/Window/Unix/Display.hpp @@ -127,6 +127,12 @@ xcb_atom_t getAtom(const std::string& name, bool onlyIfExists = false); //////////////////////////////////////////////////////////// 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 4d815f843..394911511 100644 --- a/src/SFML/Window/Unix/InputImpl.cpp +++ b/src/SFML/Window/Unix/InputImpl.cpp @@ -59,113 +59,6 @@ namespace return 255; } - - void 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; - } } @@ -423,6 +316,115 @@ 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 9425c3df4..ec4f11e9e 100644 --- a/src/SFML/Window/Unix/InputImpl.hpp +++ b/src/SFML/Window/Unix/InputImpl.hpp @@ -158,6 +158,12 @@ 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 07f27a854..7d8f984ab 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -28,6 +28,7 @@ #include // important to be included first (conflict with None) #include #include +#include #include #include #include @@ -50,6 +51,10 @@ #define XCB_DRI2_BUFFER_SWAP_COMPLETE 0 #define XCB_DRI2_INVALIDATE_BUFFERS 1 +// So we don't have to require xcb xkb to be present +#define XCB_XKB_NEW_KEYBOARD_NOTIFY 0 +#define XCB_XKB_MAP_NOTIFY 1 + #ifdef SFML_OPENGL_ES #include typedef sf::priv::EglContext ContextType; @@ -2317,6 +2322,57 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) } } + // XKEYBOARD + // When the X server sends us XKEYBOARD events, it means that + // the user probably changed the layout of their keyboard + // We update our keymaps in that case + static xcb_query_extension_reply_t xkeyboardExtension = getXExtension("XKEYBOARD"); + if (xkeyboardExtension.present && (responseType == xkeyboardExtension.first_event)) + { + // We do this so we don't have to include the xkb header for the struct declaration + uint8_t xkbType = reinterpret_cast(windowEvent)[1]; + + // We only bother rebuilding our maps if the xkb mapping actually changes + if ((xkbType == XCB_XKB_NEW_KEYBOARD_NOTIFY) || (xkbType == XCB_XKB_MAP_NOTIFY)) + { + // keysym map + buildKeysymMap(); + + // keycode to SFML + buildMap(); + + // SFML to keycode + InputImpl::buildMap(); + + // XInputMethod expects keyboard mapping changes to be propagated to it + // Same idea here as with the DRI2 events above + + // We lock/unlock the display to protect against concurrent access + XLockDisplay(m_display); + + typedef Bool (*wireEventHandler)(Display*, XEvent*, xEvent*); + + // Probe for any handlers that are registered for this event type + wireEventHandler handler = XESetWireToEvent(m_display, responseType, 0); + + if (handler) + { + // Restore the previous handler if one was registered + XESetWireToEvent(m_display, responseType, handler); + + XEvent event; + windowEvent->sequence = LastKnownRequestProcessed(m_display); + + // Pretend to be the Xlib event queue + handler(m_display, &event, reinterpret_cast(windowEvent)); + } + + XUnlockDisplay(m_display); + } + + break; + } + // Print any surprises to stderr (would be nice if people report when this happens) dumpUnhandledEvent(responseType); From cadc4d801c038bf441e7f22ee0d88110b09d3b57 Mon Sep 17 00:00:00 2001 From: Pierre-Luc Perrier Date: Fri, 22 May 2015 15:11:14 +0200 Subject: [PATCH 12/15] Fix undefined behavior in ewmhSupported() caused by some window managers not null-terminating strings. Fixes #892 --- src/SFML/Window/Unix/WindowImplX11.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 7d8f984ab..8387975c6 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -235,9 +235,12 @@ namespace sf::priv::CloseConnection(connection); - const char* name = reinterpret_cast(xcb_get_property_value(wmName.get())); - - windowManagerName = name; + // It seems the wm name string reply is not necessarily + // null-terminated. The work around is to get its actual + // length to build a proper string + const char* begin = reinterpret_cast(xcb_get_property_value(wmName.get())); + const char* end = begin + xcb_get_property_value_length(wmName.get()); + windowManagerName = sf::String::fromUtf8(begin, end); return true; } From 11357b354f620d26828c3b8bf8578ffeb40cb102 Mon Sep 17 00:00:00 2001 From: Mario Liebisch Date: Thu, 4 Jun 2015 16:55:58 +0200 Subject: [PATCH 13/15] Android: Updated the JNI/event handling code * Local Java references are now freed after use. * SFML is now able to consider (Android) events as unhandled and pass them. * Hovering a pen over the screen no longer triggers movement events (untested). --- src/SFML/Window/Android/InputImpl.cpp | 10 +++ src/SFML/Window/Android/WindowImplAndroid.cpp | 73 +++++++++++-------- src/SFML/Window/Android/WindowImplAndroid.hpp | 8 +- 3 files changed, 55 insertions(+), 36 deletions(-) diff --git a/src/SFML/Window/Android/InputImpl.cpp b/src/SFML/Window/Android/InputImpl.cpp index 920587b2a..8940b9e23 100644 --- a/src/SFML/Window/Android/InputImpl.cpp +++ b/src/SFML/Window/Android/InputImpl.cpp @@ -78,6 +78,7 @@ void InputImpl::setVirtualKeyboardVisible(bool visible) "INPUT_METHOD_SERVICE", "Ljava/lang/String;"); jobject INPUT_METHOD_SERVICE = lJNIEnv->GetStaticObjectField(ClassContext, FieldINPUT_METHOD_SERVICE); + lJNIEnv->DeleteLocalRef(ClassContext); // Runs getSystemService(Context.INPUT_METHOD_SERVICE) jclass ClassInputMethodManager = @@ -86,6 +87,7 @@ void InputImpl::setVirtualKeyboardVisible(bool visible) "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"); jobject lInputMethodManager = lJNIEnv->CallObjectMethod(lNativeActivity, MethodGetSystemService, INPUT_METHOD_SERVICE); + lJNIEnv->DeleteLocalRef(INPUT_METHOD_SERVICE); // Runs getWindow().getDecorView() jmethodID MethodGetWindow = lJNIEnv->GetMethodID(ClassNativeActivity, @@ -95,6 +97,8 @@ void InputImpl::setVirtualKeyboardVisible(bool visible) jmethodID MethodGetDecorView = lJNIEnv->GetMethodID(ClassWindow, "getDecorView", "()Landroid/view/View;"); jobject lDecorView = lJNIEnv->CallObjectMethod(lWindow, MethodGetDecorView); + lJNIEnv->DeleteLocalRef(lWindow); + lJNIEnv->DeleteLocalRef(ClassWindow); if (visible) { @@ -112,13 +116,19 @@ void InputImpl::setVirtualKeyboardVisible(bool visible) "getWindowToken", "()Landroid/os/IBinder;"); jobject lBinder = lJNIEnv->CallObjectMethod(lDecorView, MethodGetWindowToken); + lJNIEnv->DeleteLocalRef(ClassView); // lInputMethodManager.hideSoftInput(...) jmethodID MethodHideSoftInput = lJNIEnv->GetMethodID(ClassInputMethodManager, "hideSoftInputFromWindow", "(Landroid/os/IBinder;I)Z"); jboolean lRes = lJNIEnv->CallBooleanMethod(lInputMethodManager, MethodHideSoftInput, lBinder, lFlags); + lJNIEnv->DeleteLocalRef(lBinder); } + lJNIEnv->DeleteLocalRef(lNativeActivity); + lJNIEnv->DeleteLocalRef(ClassNativeActivity); + lJNIEnv->DeleteLocalRef(ClassInputMethodManager); + lJNIEnv->DeleteLocalRef(lDecorView); // Finished with the JVM lJavaVM->DetachCurrentThread(); diff --git a/src/SFML/Window/Android/WindowImplAndroid.cpp b/src/SFML/Window/Android/WindowImplAndroid.cpp index 2c140b057..fb1906bbb 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.cpp +++ b/src/SFML/Window/Android/WindowImplAndroid.cpp @@ -33,9 +33,11 @@ #include #include -// Define missing constants -#define AMOTION_EVENT_ACTION_HOVER_MOVE 0x00000007 -#define AMOTION_EVENT_ACTION_SCROLL 0x00000008 +// Define missing constants for older API levels +#if __ANDROID_API__ < 13 + #define AMOTION_EVENT_ACTION_HOVER_MOVE 0x00000007 + #define AMOTION_EVENT_ACTION_SCROLL 0x00000008 +#endif //////////////////////////////////////////////////////////// // Private data @@ -232,7 +234,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data) if (AInputQueue_preDispatchEvent(states->inputQueue, _event)) return 1; - int32_t handled = 0; + int handled = 0; int32_t type = AInputEvent_getType(_event); @@ -244,8 +246,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data) if ((action == AKEY_EVENT_ACTION_DOWN || action == AKEY_EVENT_ACTION_UP || action == AKEY_EVENT_ACTION_MULTIPLE) && key != AKEYCODE_VOLUME_UP && key != AKEYCODE_VOLUME_DOWN) { - processKeyEvent(_event, states); - handled = 1; + handled = processKeyEvent(_event, states); } } else if (type == AINPUT_EVENT_TYPE_MOTION) @@ -256,16 +257,15 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data) { case AMOTION_EVENT_ACTION_SCROLL: { - processScrollEvent(_event, states); - handled = 1; + handled = processScrollEvent(_event, states); break; } - case AMOTION_EVENT_ACTION_HOVER_MOVE: + // todo: should hover_move indeed trigger the event? + // case AMOTION_EVENT_ACTION_HOVER_MOVE: case AMOTION_EVENT_ACTION_MOVE: { - processMotionEvent(_event, states); - handled = 1; + handled = processMotionEvent(_event, states); break; } @@ -273,8 +273,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data) case AMOTION_EVENT_ACTION_POINTER_DOWN: case AMOTION_EVENT_ACTION_DOWN: { - processPointerEvent(true, _event, states); - handled = 1; + handled = processPointerEvent(true, _event, states); break; } @@ -282,8 +281,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data) case AMOTION_EVENT_ACTION_UP: case AMOTION_EVENT_ACTION_CANCEL: { - processPointerEvent(false, _event, states); - handled = 1; + handled = processPointerEvent(false, _event, states); break; } } @@ -298,7 +296,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data) //////////////////////////////////////////////////////////// -void WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates* states) +int WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates* states) { // Prepare the Java virtual machine jint lResult; @@ -314,8 +312,10 @@ void WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates* lResult=lJavaVM->AttachCurrentThread(&lJNIEnv, &lJavaVMAttachArgs); - if (lResult == JNI_ERR) + if (lResult == JNI_ERR) { err() << "Failed to initialize JNI, couldn't get the Unicode value" << std::endl; + return 0; + } // Retrieve everything we need to create this MotionEvent in Java jlong downTime = AMotionEvent_getDownTime(_event); @@ -340,6 +340,9 @@ void WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates* jmethodID MethodGetAxisValue = lJNIEnv->GetMethodID(ClassMotionEvent, "getAxisValue", "(I)F"); jfloat delta = lJNIEnv->CallFloatMethod(ObjectMotionEvent, MethodGetAxisValue, 0x00000001); + lJNIEnv->DeleteLocalRef(ClassMotionEvent); + lJNIEnv->DeleteLocalRef(ObjectMotionEvent); + // Create and send our mouse wheel event Event event; event.type = Event::MouseWheelMoved; @@ -351,11 +354,13 @@ void WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates* // Detach this thread from the JVM lJavaVM->DetachCurrentThread(); + + return 1; } //////////////////////////////////////////////////////////// -void WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* states) +int WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* states) { int32_t device = AInputEvent_getSource(_event); int32_t action = AKeyEvent_getAction(_event); @@ -374,7 +379,7 @@ void WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* sta case AKEY_EVENT_ACTION_DOWN: event.type = Event::KeyPressed; forwardEvent(event); - break; + return 1; case AKEY_EVENT_ACTION_UP: event.type = Event::KeyReleased; forwardEvent(event); @@ -385,7 +390,7 @@ void WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* sta event.text.unicode = unicode; forwardEvent(event); } - break; + return 1; case AKEY_EVENT_ACTION_MULTIPLE: // Since complex inputs don't get separate key down/up events // both have to be faked at once @@ -400,27 +405,26 @@ void WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* sta { // This is a unique sequence, which is not yet exposed in the NDK // http://code.google.com/p/android/issues/detail?id=33998 + return 0; } - else + else if (int unicode = getUnicode(_event)) // This is a repeated sequence { - // This is a repeated sequence - if (int unicode = getUnicode(_event)) - { - event.type = Event::TextEntered; - event.text.unicode = unicode; + event.type = Event::TextEntered; + event.text.unicode = unicode; - int32_t repeats = AKeyEvent_getRepeatCount(_event); - for (int32_t i = 0; i < repeats; ++i) - forwardEvent(event); - } + int32_t repeats = AKeyEvent_getRepeatCount(_event); + for (int32_t i = 0; i < repeats; ++i) + forwardEvent(event); + return 1; } break; } + return 0; } //////////////////////////////////////////////////////////// -void WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates* states) +int WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates* states) { int32_t device = AInputEvent_getSource(_event); int32_t action = AMotionEvent_getAction(_event); @@ -462,11 +466,12 @@ void WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates* forwardEvent(event); } + return 1; } //////////////////////////////////////////////////////////// -void WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, ActivityStates* states) +int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, ActivityStates* states) { int32_t device = AInputEvent_getSource(_event); int32_t action = AMotionEvent_getAction(_event); @@ -525,6 +530,7 @@ void WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Ac } forwardEvent(event); + return 1; } @@ -693,6 +699,9 @@ int WindowImplAndroid::getUnicode(AInputEvent* event) jmethodID MethodGetUnicode = lJNIEnv->GetMethodID(ClassKeyEvent, "getUnicodeChar", "(I)I"); int unicode = lJNIEnv->CallIntMethod(ObjectKeyEvent, MethodGetUnicode, metaState); + lJNIEnv->DeleteLocalRef(ClassKeyEvent); + lJNIEnv->DeleteLocalRef(ObjectKeyEvent); + // Detach this thread from the JVM lJavaVM->DetachCurrentThread(); diff --git a/src/SFML/Window/Android/WindowImplAndroid.hpp b/src/SFML/Window/Android/WindowImplAndroid.hpp index cdfb5217e..fb05b35b0 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.hpp +++ b/src/SFML/Window/Android/WindowImplAndroid.hpp @@ -194,10 +194,10 @@ private: //////////////////////////////////////////////////////////// static int processEvent(int fd, int events, void* data); - static void processScrollEvent(AInputEvent* _event, ActivityStates* states); - static void processKeyEvent(AInputEvent* _event, ActivityStates* states); - static void processMotionEvent(AInputEvent* _event, ActivityStates* states); - static void processPointerEvent(bool isDown, AInputEvent* event, ActivityStates* states); + static int processScrollEvent(AInputEvent* _event, ActivityStates* states); + static int processKeyEvent(AInputEvent* _event, ActivityStates* states); + static int processMotionEvent(AInputEvent* _event, ActivityStates* states); + static int processPointerEvent(bool isDown, AInputEvent* event, ActivityStates* states); //////////////////////////////////////////////////////////// /// \brief Convert a Android key to SFML key code From 2d56b412653c5df6624e1c139e94aa2086bd8183 Mon Sep 17 00:00:00 2001 From: binary1248 Date: Mon, 22 Jun 2015 11:47:32 +0200 Subject: [PATCH 14/15] Added 2.3.1 changes to changelog. --- changelog.txt | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/changelog.txt b/changelog.txt index b4944c3cd..c6bd66133 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,39 @@ +SFML 2.3.1 +========== + +Also available on the website: http://www.sfml-dev.org/changelog.php#sfml-2.3.1 + +Window +====== + +Bugfixes +-------- +* [Android] Make sure a window still exists before trying to access its dimensions (#854) +* [Android] Added Android API level checks (#856) +* [Android] Updated the JNI/event handling code (#906) +* [Linux] Resized events are only spawned when the window size actually changes (#878, #893) +* [Linux] Whitelisted X SHAPE events (#879, #883) +* [Linux] Remap Unix keyboard when user changes layout (#895, #897) +* [Linux] Fix undefined behavior in ewmhSupported() (#892, #901) + + +Graphics +======== + +Bugfixes +-------- +* Added support for GL_EXT_texture_edge_clamp for systems that don't expose GL_SGIS_texture_edge_clamp (#880, #882) + + +Audio +===== + +Bugfixes +-------- +* [Android] Fixed audio files not loading (and possibly crashing) (#855, #887) + + + SFML 2.3 ======== From b735777c4ade9d9b184576e664a4a26d7cdd8ecd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Fri, 22 May 2015 19:52:06 +0200 Subject: [PATCH 15/15] Increased version to 2.3.1. --- CMakeLists.txt | 2 +- include/SFML/Config.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ac15c3c6..ee11ead1e 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 0) +set(VERSION_PATCH 1) # add the SFML header path include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) diff --git a/include/SFML/Config.hpp b/include/SFML/Config.hpp index 58e979746..294f28269 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 0 +#define SFML_VERSION_PATCH 1 ////////////////////////////////////////////////////////////