From f162b3a0377195a6c3c81312251ca721d1ee5aba Mon Sep 17 00:00:00 2001 From: Vittorio Romeo Date: Wed, 14 Apr 2021 02:59:13 +0100 Subject: [PATCH] Enable support for unity builds --- .github/workflows/ci.yml | 6 +- examples/voip/Client.cpp | 8 +- examples/voip/Server.cpp | 8 +- src/SFML/Graphics/GLExtensions.cpp | 9 +- src/SFML/Graphics/RenderTarget.cpp | 178 +++--- src/SFML/Graphics/Texture.cpp | 40 +- src/SFML/Graphics/VertexBuffer.cpp | 26 +- src/SFML/Window/Context.cpp | 12 +- src/SFML/Window/EglContext.cpp | 75 ++- src/SFML/Window/GlContext.cpp | 336 +++++----- src/SFML/Window/Unix/GlxContext.cpp | 11 +- src/SFML/Window/Unix/WindowImplX11.cpp | 726 +++++++++++----------- src/SFML/Window/Win32/VulkanImplWin32.cpp | 2 + src/SFML/Window/Win32/WglContext.cpp | 81 +-- src/SFML/Window/Win32/WindowImplWin32.cpp | 3 + src/SFML/Window/WindowBase.cpp | 10 +- 16 files changed, 839 insertions(+), 692 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fc0280f93..12cf787fa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,10 +17,12 @@ jobs: - { name: Linux Clang, os: ubuntu-latest, flags: -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ } - { name: MacOS XCode, os: macos-latest } config: - - { name: Shared, flags: -DBUILD_SHARED_LIBS=TRUE } - - { name: Static, flags: -DBUILD_SHARED_LIBS=FALSE } + - { name: Shared, flags: -DBUILD_SHARED_LIBS=TRUE } + - { name: Static, flags: -DBUILD_SHARED_LIBS=FALSE } include: + - platform: { name: Windows VS2019, os: windows-latest } + config: { name: Unity, flags: -DBUILD_SHARED_LIBS=TRUE -DCMAKE_UNITY_BUILD=ON } - platform: { name: MacOS XCode, os: macos-latest } config: { name: Frameworks, flags: -DSFML_BUILD_FRAMEWORKS=TRUE } - platform: { name: MacOS XCode, os: macos-latest } diff --git a/examples/voip/Client.cpp b/examples/voip/Client.cpp index d66e0e231..300370989 100644 --- a/examples/voip/Client.cpp +++ b/examples/voip/Client.cpp @@ -7,8 +7,8 @@ #include -const sf::Uint8 audioData = 1; -const sf::Uint8 endOfStream = 2; +const sf::Uint8 clientAudioData = 1; +const sf::Uint8 clientEndOfStream = 2; //////////////////////////////////////////////////////////// @@ -71,7 +71,7 @@ private: { // Pack the audio samples into a network packet sf::Packet packet; - packet << audioData; + packet << clientAudioData; packet.append(samples, sampleCount * sizeof(sf::Int16)); // Send the audio packet to the server @@ -86,7 +86,7 @@ private: { // Send a "end-of-stream" packet sf::Packet packet; - packet << endOfStream; + packet << clientEndOfStream; m_socket.send(packet); // Close the socket diff --git a/examples/voip/Server.cpp b/examples/voip/Server.cpp index 0875bf956..9c705539b 100644 --- a/examples/voip/Server.cpp +++ b/examples/voip/Server.cpp @@ -9,8 +9,8 @@ #include -const sf::Uint8 audioData = 1; -const sf::Uint8 endOfStream = 2; +const sf::Uint8 serverAudioData = 1; +const sf::Uint8 serverEndOfStream = 2; //////////////////////////////////////////////////////////// @@ -123,7 +123,7 @@ private: sf::Uint8 id; packet >> id; - if (id == audioData) + if (id == serverAudioData) { // Extract audio samples from the packet, and append it to our samples buffer const sf::Int16* samples = reinterpret_cast(static_cast(packet.getData()) + 1); @@ -136,7 +136,7 @@ private: std::copy(samples, samples + sampleCount, std::back_inserter(m_samples)); } } - else if (id == endOfStream) + else if (id == serverEndOfStream) { // End of stream reached: we stop receiving audio data std::cout << "Audio data has been 100% received!" << std::endl; diff --git a/src/SFML/Graphics/GLExtensions.cpp b/src/SFML/Graphics/GLExtensions.cpp index 5ec9236e3..a18326fb9 100644 --- a/src/SFML/Graphics/GLExtensions.cpp +++ b/src/SFML/Graphics/GLExtensions.cpp @@ -25,11 +25,18 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#define SF_GLAD_GL_IMPLEMENTATION #include #include #include +// We check for this definition in order to avoid multiple definitions of GLAD +// entities during unity builds of SFML. +#ifndef SF_GLAD_GL_IMPLEMENTATION_INCLUDED +#define SF_GLAD_GL_IMPLEMENTATION_INCLUDED +#define SF_GLAD_GL_IMPLEMENTATION +#include +#endif + #if !defined(GL_MAJOR_VERSION) #define GL_MAJOR_VERSION 0x821B #endif diff --git a/src/SFML/Graphics/RenderTarget.cpp b/src/SFML/Graphics/RenderTarget.cpp index 9066d9960..7372c40b5 100644 --- a/src/SFML/Graphics/RenderTarget.cpp +++ b/src/SFML/Graphics/RenderTarget.cpp @@ -52,95 +52,99 @@ namespace { - // Mutex to protect ID generation and our context-RenderTarget-map - sf::Mutex mutex; - - // Unique identifier, used for identifying RenderTargets when - // tracking the currently active RenderTarget within a given context - sf::Uint64 getUniqueId() + // A nested named namespace is used here to allow unity builds of SFML. + namespace RenderTargetImpl { - sf::Lock lock(mutex); + // Mutex to protect ID generation and our context-RenderTarget-map + sf::Mutex mutex; - static sf::Uint64 id = 1; // start at 1, zero is "no RenderTarget" - - return id++; - } - - // Map to help us detect whether a different RenderTarget - // has been activated within a single context - typedef std::map ContextRenderTargetMap; - ContextRenderTargetMap contextRenderTargetMap; - - // Check if a RenderTarget with the given ID is active in the current context - bool isActive(sf::Uint64 id) - { - ContextRenderTargetMap::iterator iter = contextRenderTargetMap.find(sf::Context::getActiveContextId()); - - if ((iter == contextRenderTargetMap.end()) || (iter->second != id)) - return false; - - return true; - } - - // Convert an sf::BlendMode::Factor constant to the corresponding OpenGL constant. - sf::Uint32 factorToGlConstant(sf::BlendMode::Factor blendFactor) - { - switch (blendFactor) + // Unique identifier, used for identifying RenderTargets when + // tracking the currently active RenderTarget within a given context + sf::Uint64 getUniqueId() { - case sf::BlendMode::Zero: return GL_ZERO; - case sf::BlendMode::One: return GL_ONE; - case sf::BlendMode::SrcColor: return GL_SRC_COLOR; - case sf::BlendMode::OneMinusSrcColor: return GL_ONE_MINUS_SRC_COLOR; - case sf::BlendMode::DstColor: return GL_DST_COLOR; - case sf::BlendMode::OneMinusDstColor: return GL_ONE_MINUS_DST_COLOR; - case sf::BlendMode::SrcAlpha: return GL_SRC_ALPHA; - case sf::BlendMode::OneMinusSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA; - case sf::BlendMode::DstAlpha: return GL_DST_ALPHA; - case sf::BlendMode::OneMinusDstAlpha: return GL_ONE_MINUS_DST_ALPHA; + sf::Lock lock(mutex); + + static sf::Uint64 id = 1; // start at 1, zero is "no RenderTarget" + + return id++; } - sf::err() << "Invalid value for sf::BlendMode::Factor! Fallback to sf::BlendMode::Zero." << std::endl; - assert(false); - return GL_ZERO; - } + // Map to help us detect whether a different RenderTarget + // has been activated within a single context + typedef std::map ContextRenderTargetMap; + ContextRenderTargetMap contextRenderTargetMap; - - // Convert an sf::BlendMode::BlendEquation constant to the corresponding OpenGL constant. - sf::Uint32 equationToGlConstant(sf::BlendMode::Equation blendEquation) - { - switch (blendEquation) + // Check if a RenderTarget with the given ID is active in the current context + bool isActive(sf::Uint64 id) { - case sf::BlendMode::Add: - return GLEXT_GL_FUNC_ADD; - case sf::BlendMode::Subtract: - if (GLEXT_blend_subtract) - return GLEXT_GL_FUNC_SUBTRACT; - break; - case sf::BlendMode::ReverseSubtract: - if (GLEXT_blend_subtract) - return GLEXT_GL_FUNC_REVERSE_SUBTRACT; - break; - case sf::BlendMode::Min: - if (GLEXT_blend_minmax) - return GLEXT_GL_MIN; - break; - case sf::BlendMode::Max: - if (GLEXT_blend_minmax) - return GLEXT_GL_MAX; - break; + ContextRenderTargetMap::iterator iter = contextRenderTargetMap.find(sf::Context::getActiveContextId()); + + if ((iter == contextRenderTargetMap.end()) || (iter->second != id)) + return false; + + return true; } - static bool warned = false; - if (!warned) + // Convert an sf::BlendMode::Factor constant to the corresponding OpenGL constant. + sf::Uint32 factorToGlConstant(sf::BlendMode::Factor blendFactor) { - sf::err() << "OpenGL extension EXT_blend_minmax or EXT_blend_subtract unavailable" << std::endl; - sf::err() << "Some blending equations will fallback to sf::BlendMode::Add" << std::endl; - sf::err() << "Ensure that hardware acceleration is enabled if available" << std::endl; + switch (blendFactor) + { + case sf::BlendMode::Zero: return GL_ZERO; + case sf::BlendMode::One: return GL_ONE; + case sf::BlendMode::SrcColor: return GL_SRC_COLOR; + case sf::BlendMode::OneMinusSrcColor: return GL_ONE_MINUS_SRC_COLOR; + case sf::BlendMode::DstColor: return GL_DST_COLOR; + case sf::BlendMode::OneMinusDstColor: return GL_ONE_MINUS_DST_COLOR; + case sf::BlendMode::SrcAlpha: return GL_SRC_ALPHA; + case sf::BlendMode::OneMinusSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA; + case sf::BlendMode::DstAlpha: return GL_DST_ALPHA; + case sf::BlendMode::OneMinusDstAlpha: return GL_ONE_MINUS_DST_ALPHA; + } - warned = true; + sf::err() << "Invalid value for sf::BlendMode::Factor! Fallback to sf::BlendMode::Zero." << std::endl; + assert(false); + return GL_ZERO; } - return GLEXT_GL_FUNC_ADD; + + // Convert an sf::BlendMode::BlendEquation constant to the corresponding OpenGL constant. + sf::Uint32 equationToGlConstant(sf::BlendMode::Equation blendEquation) + { + switch (blendEquation) + { + case sf::BlendMode::Add: + return GLEXT_GL_FUNC_ADD; + case sf::BlendMode::Subtract: + if (GLEXT_blend_subtract) + return GLEXT_GL_FUNC_SUBTRACT; + break; + case sf::BlendMode::ReverseSubtract: + if (GLEXT_blend_subtract) + return GLEXT_GL_FUNC_REVERSE_SUBTRACT; + break; + case sf::BlendMode::Min: + if (GLEXT_blend_minmax) + return GLEXT_GL_MIN; + break; + case sf::BlendMode::Max: + if (GLEXT_blend_minmax) + return GLEXT_GL_MAX; + break; + } + + static bool warned = false; + if (!warned) + { + sf::err() << "OpenGL extension EXT_blend_minmax or EXT_blend_subtract unavailable" << std::endl; + sf::err() << "Some blending equations will fallback to sf::BlendMode::Add" << std::endl; + sf::err() << "Ensure that hardware acceleration is enabled if available" << std::endl; + + warned = true; + } + + return GLEXT_GL_FUNC_ADD; + } } } @@ -167,7 +171,7 @@ RenderTarget::~RenderTarget() //////////////////////////////////////////////////////////// void RenderTarget::clear(const Color& color) { - if (isActive(m_id) || setActive(true)) + if (RenderTargetImpl::isActive(m_id) || setActive(true)) { // Unbind texture to fix RenderTexture preventing clear applyTexture(NULL); @@ -282,7 +286,7 @@ void RenderTarget::draw(const Vertex* vertices, std::size_t vertexCount, } #endif - if (isActive(m_id) || setActive(true)) + if (RenderTargetImpl::isActive(m_id) || setActive(true)) { // Check if the vertex count is low enough so that we can pre-transform them bool useVertexCache = (vertexCount <= StatesCache::VertexCacheSize); @@ -382,7 +386,7 @@ void RenderTarget::draw(const VertexBuffer& vertexBuffer, std::size_t firstVerte } #endif - if (isActive(m_id) || setActive(true)) + if (RenderTargetImpl::isActive(m_id) || setActive(true)) { setupDraw(false, states); @@ -424,11 +428,12 @@ bool RenderTarget::setActive(bool active) { // Mark this RenderTarget as active or no longer active in the tracking map { - sf::Lock lock(mutex); + sf::Lock lock(RenderTargetImpl::mutex); Uint64 contextId = Context::getActiveContextId(); - ContextRenderTargetMap::iterator iter = contextRenderTargetMap.find(contextId); + using RenderTargetImpl::contextRenderTargetMap; + RenderTargetImpl::ContextRenderTargetMap::iterator iter = contextRenderTargetMap.find(contextId); if (active) { @@ -462,7 +467,7 @@ bool RenderTarget::setActive(bool active) //////////////////////////////////////////////////////////// void RenderTarget::pushGLStates() { - if (isActive(m_id) || setActive(true)) + if (RenderTargetImpl::isActive(m_id) || setActive(true)) { #ifdef SFML_DEBUG // make sure that the user didn't leave an unchecked OpenGL error @@ -494,7 +499,7 @@ void RenderTarget::pushGLStates() //////////////////////////////////////////////////////////// void RenderTarget::popGLStates() { - if (isActive(m_id) || setActive(true)) + if (RenderTargetImpl::isActive(m_id) || setActive(true)) { glCheck(glMatrixMode(GL_PROJECTION)); glCheck(glPopMatrix()); @@ -523,7 +528,7 @@ void RenderTarget::resetGLStates() setActive(false); #endif - if (isActive(m_id) || setActive(true)) + if (RenderTargetImpl::isActive(m_id) || setActive(true)) { // Make sure that extensions are initialized priv::ensureExtensionsInit(); @@ -582,7 +587,7 @@ void RenderTarget::initialize() // Generate a unique ID for this RenderTarget to track // whether it is active within a specific context - m_id = getUniqueId(); + m_id = RenderTargetImpl::getUniqueId(); } @@ -608,6 +613,9 @@ void RenderTarget::applyCurrentView() //////////////////////////////////////////////////////////// void RenderTarget::applyBlendMode(const BlendMode& mode) { + using RenderTargetImpl::factorToGlConstant; + using RenderTargetImpl::equationToGlConstant; + // Apply the blend mode, falling back to the non-separate versions if necessary if (GLEXT_blend_func_separate) { diff --git a/src/SFML/Graphics/Texture.cpp b/src/SFML/Graphics/Texture.cpp index 9da32b05b..0df24a7a2 100644 --- a/src/SFML/Graphics/Texture.cpp +++ b/src/SFML/Graphics/Texture.cpp @@ -40,18 +40,22 @@ namespace { - sf::Mutex idMutex; - sf::Mutex maximumSizeMutex; - - // Thread-safe unique identifier generator, - // is used for states cache (see RenderTarget) - sf::Uint64 getUniqueId() + // A nested named namespace is used here to allow unity builds of SFML. + namespace TextureImpl { - sf::Lock lock(idMutex); + sf::Mutex idMutex; + sf::Mutex maximumSizeMutex; - static sf::Uint64 id = 1; // start at 1, zero is "no texture" + // Thread-safe unique identifier generator, + // is used for states cache (see RenderTarget) + sf::Uint64 getUniqueId() + { + sf::Lock lock(idMutex); - return id++; + static sf::Uint64 id = 1; // start at 1, zero is "no texture" + + return id++; + } } } @@ -69,7 +73,7 @@ m_isRepeated (false), m_pixelsFlipped(false), m_fboAttachment(false), m_hasMipmap (false), -m_cacheId (getUniqueId()) +m_cacheId (TextureImpl::getUniqueId()) { } @@ -85,7 +89,7 @@ m_isRepeated (copy.m_isRepeated), m_pixelsFlipped(false), m_fboAttachment(false), m_hasMipmap (false), -m_cacheId (getUniqueId()) +m_cacheId (TextureImpl::getUniqueId()) { if (copy.m_texture) { @@ -206,7 +210,7 @@ bool Texture::create(unsigned int width, unsigned int height) 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(); + m_cacheId = TextureImpl::getUniqueId(); m_hasMipmap = false; @@ -422,7 +426,7 @@ void Texture::update(const Uint8* pixels, unsigned int width, unsigned int heigh glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST)); m_hasMipmap = false; m_pixelsFlipped = false; - m_cacheId = getUniqueId(); + m_cacheId = TextureImpl::getUniqueId(); // Force an OpenGL flush, so that the texture data will appear updated // in all contexts immediately (solves problems in multi-threaded apps) @@ -525,7 +529,7 @@ void Texture::update(const Texture& texture, unsigned int x, unsigned int y) glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST)); m_hasMipmap = false; m_pixelsFlipped = false; - m_cacheId = getUniqueId(); + m_cacheId = TextureImpl::getUniqueId(); // Force an OpenGL flush, so that the texture data will appear updated // in all contexts immediately (solves problems in multi-threaded apps) @@ -581,7 +585,7 @@ void Texture::update(const Window& window, unsigned int x, unsigned int y) glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST)); m_hasMipmap = false; m_pixelsFlipped = true; - m_cacheId = getUniqueId(); + m_cacheId = TextureImpl::getUniqueId(); // Force an OpenGL flush, so that the texture will appear updated // in all contexts immediately (solves problems in multi-threaded apps) @@ -790,7 +794,7 @@ void Texture::bind(const Texture* texture, CoordinateType coordinateType) //////////////////////////////////////////////////////////// unsigned int Texture::getMaximumSize() { - Lock lock(maximumSizeMutex); + Lock lock(TextureImpl::maximumSizeMutex); static bool checked = false; static GLint size = 0; @@ -832,8 +836,8 @@ void Texture::swap(Texture& right) std::swap(m_fboAttachment, right.m_fboAttachment); std::swap(m_hasMipmap, right.m_hasMipmap); - m_cacheId = getUniqueId(); - right.m_cacheId = getUniqueId(); + m_cacheId = TextureImpl::getUniqueId(); + right.m_cacheId = TextureImpl::getUniqueId(); } diff --git a/src/SFML/Graphics/VertexBuffer.cpp b/src/SFML/Graphics/VertexBuffer.cpp index 18a9b70e9..9fb1a853d 100644 --- a/src/SFML/Graphics/VertexBuffer.cpp +++ b/src/SFML/Graphics/VertexBuffer.cpp @@ -36,15 +36,19 @@ namespace { - sf::Mutex isAvailableMutex; - - GLenum usageToGlEnum(sf::VertexBuffer::Usage usage) + // A nested named namespace is used here to allow unity builds of SFML. + namespace VertexBufferImpl { - switch (usage) + sf::Mutex isAvailableMutex; + + GLenum usageToGlEnum(sf::VertexBuffer::Usage usage) { - case sf::VertexBuffer::Static: return GLEXT_GL_STATIC_DRAW; - case sf::VertexBuffer::Dynamic: return GLEXT_GL_DYNAMIC_DRAW; - default: return GLEXT_GL_STREAM_DRAW; + switch (usage) + { + case sf::VertexBuffer::Static: return GLEXT_GL_STATIC_DRAW; + case sf::VertexBuffer::Dynamic: return GLEXT_GL_DYNAMIC_DRAW; + default: return GLEXT_GL_STREAM_DRAW; + } } } } @@ -143,7 +147,7 @@ bool VertexBuffer::create(std::size_t vertexCount) } glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, m_buffer)); - glCheck(GLEXT_glBufferData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * vertexCount, 0, usageToGlEnum(m_usage))); + glCheck(GLEXT_glBufferData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * vertexCount, 0, VertexBufferImpl::usageToGlEnum(m_usage))); glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, 0)); m_size = vertexCount; @@ -186,7 +190,7 @@ bool VertexBuffer::update(const Vertex* vertices, std::size_t vertexCount, unsig // Check if we need to resize or orphan the buffer if (vertexCount >= m_size) { - glCheck(GLEXT_glBufferData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * vertexCount, 0, usageToGlEnum(m_usage))); + glCheck(GLEXT_glBufferData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * vertexCount, 0, VertexBufferImpl::usageToGlEnum(m_usage))); m_size = vertexCount; } @@ -230,7 +234,7 @@ bool VertexBuffer::update(const VertexBuffer& vertexBuffer) } glCheck(GLEXT_glBindBuffer(GLEXT_GL_ARRAY_BUFFER, m_buffer)); - glCheck(GLEXT_glBufferData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * vertexBuffer.m_size, 0, usageToGlEnum(m_usage))); + glCheck(GLEXT_glBufferData(GLEXT_GL_ARRAY_BUFFER, sizeof(Vertex) * vertexBuffer.m_size, 0, VertexBufferImpl::usageToGlEnum(m_usage))); void* destination = 0; glCheck(destination = GLEXT_glMapBuffer(GLEXT_GL_ARRAY_BUFFER, GLEXT_GL_WRITE_ONLY)); @@ -332,7 +336,7 @@ VertexBuffer::Usage VertexBuffer::getUsage() const //////////////////////////////////////////////////////////// bool VertexBuffer::isAvailable() { - Lock lock(isAvailableMutex); + Lock lock(VertexBufferImpl::isAvailableMutex); static bool checked = false; static bool available = false; diff --git a/src/SFML/Window/Context.cpp b/src/SFML/Window/Context.cpp index d10c48c3d..dd74ced48 100644 --- a/src/SFML/Window/Context.cpp +++ b/src/SFML/Window/Context.cpp @@ -32,8 +32,12 @@ namespace { - // This per-thread variable holds the last activated sf::Context for each thread - sf::ThreadLocalPtr currentContext(NULL); + // A nested named namespace is used here to allow unity builds of SFML. + namespace ContextImpl + { + // This per-thread variable holds the current context for each thread + sf::ThreadLocalPtr currentContext(NULL); + } } namespace sf @@ -60,7 +64,7 @@ bool Context::setActive(bool active) bool result = m_context->setActive(active); if (result) - currentContext = (active ? this : NULL); + ContextImpl::currentContext = (active ? this : NULL); return result; } @@ -76,6 +80,8 @@ const ContextSettings& Context::getSettings() const //////////////////////////////////////////////////////////// const Context* Context::getActiveContext() { + using ContextImpl::currentContext; + // We have to check that the last activated sf::Context is still active (a RenderTarget activation may have deactivated it) if (currentContext && currentContext->m_context == priv::GlContext::getActiveContext()) return currentContext; diff --git a/src/SFML/Window/EglContext.cpp b/src/SFML/Window/EglContext.cpp index 93b6949f3..95dba581e 100644 --- a/src/SFML/Window/EglContext.cpp +++ b/src/SFML/Window/EglContext.cpp @@ -39,49 +39,58 @@ #include #endif +// We check for this definition in order to avoid multiple definitions of GLAD +// entities during unity builds of SFML. +#ifndef SF_GLAD_EGL_IMPLEMENTATION_INCLUDED +#define SF_GLAD_EGL_IMPLEMENTATION_INCLUDED #define SF_GLAD_EGL_IMPLEMENTATION #include +#endif namespace { - EGLDisplay getInitializedDisplay() + // A nested named namespace is used here to allow unity builds of SFML. + namespace EglContextImpl { + EGLDisplay getInitializedDisplay() + { #if defined(SFML_SYSTEM_ANDROID) - // On Android, its native activity handles this for us - sf::priv::ActivityStates* states = sf::priv::getActivity(NULL); - sf::Lock lock(states->mutex); + // On Android, its native activity handles this for us + sf::priv::ActivityStates* states = sf::priv::getActivity(NULL); + sf::Lock lock(states->mutex); - return states->display; + return states->display; #endif - static EGLDisplay display = EGL_NO_DISPLAY; + static EGLDisplay display = EGL_NO_DISPLAY; - if (display == EGL_NO_DISPLAY) - { - eglCheck(display = eglGetDisplay(EGL_DEFAULT_DISPLAY)); - eglCheck(eglInitialize(display, NULL, NULL)); + if (display == EGL_NO_DISPLAY) + { + eglCheck(display = eglGetDisplay(EGL_DEFAULT_DISPLAY)); + eglCheck(eglInitialize(display, NULL, NULL)); + } + + return display; } - return display; - } - - //////////////////////////////////////////////////////////// - void ensureInit() - { - static bool initialized = false; - if (!initialized) + //////////////////////////////////////////////////////////// + void ensureInit() { - initialized = true; + static bool initialized = false; + if (!initialized) + { + initialized = true; - // We don't check the return value since the extension - // flags are cleared even if loading fails - gladLoaderLoadEGL(EGL_NO_DISPLAY); + // We don't check the return value since the extension + // flags are cleared even if loading fails + gladLoaderLoadEGL(EGL_NO_DISPLAY); - // Continue loading with a display - gladLoaderLoadEGL(getInitializedDisplay()); + // Continue loading with a display + gladLoaderLoadEGL(getInitializedDisplay()); + } } } } @@ -98,10 +107,10 @@ m_context (EGL_NO_CONTEXT), m_surface (EGL_NO_SURFACE), m_config (NULL) { - ensureInit(); + EglContextImpl::ensureInit(); // Get the initialized EGL display - m_display = getInitializedDisplay(); + m_display = EglContextImpl::getInitializedDisplay(); // Get the best EGL config matching the default video settings m_config = getBestConfig(m_display, VideoMode::getDesktopMode().bitsPerPixel, ContextSettings()); @@ -129,7 +138,7 @@ m_context (EGL_NO_CONTEXT), m_surface (EGL_NO_SURFACE), m_config (NULL) { - ensureInit(); + EglContextImpl::ensureInit(); #ifdef SFML_SYSTEM_ANDROID @@ -142,7 +151,7 @@ m_config (NULL) #endif // Get the initialized EGL display - m_display = getInitializedDisplay(); + m_display = EglContextImpl::getInitializedDisplay(); // Get the best EGL config matching the requested video settings m_config = getBestConfig(m_display, bitsPerPixel, settings); @@ -166,7 +175,7 @@ m_context (EGL_NO_CONTEXT), m_surface (EGL_NO_SURFACE), m_config (NULL) { - ensureInit(); + EglContextImpl::ensureInit(); } @@ -202,7 +211,7 @@ EglContext::~EglContext() //////////////////////////////////////////////////////////// GlFunctionPointer EglContext::getFunction(const char* name) { - ensureInit(); + EglContextImpl::ensureInit(); return reinterpret_cast(eglGetProcAddress(name)); } @@ -288,7 +297,7 @@ void EglContext::destroySurface() //////////////////////////////////////////////////////////// EGLConfig EglContext::getBestConfig(EGLDisplay display, unsigned int bitsPerPixel, const ContextSettings& settings) { - ensureInit(); + EglContextImpl::ensureInit(); // Set our video settings constraint const EGLint attributes[] = { @@ -352,10 +361,10 @@ void EglContext::updateSettings() //////////////////////////////////////////////////////////// XVisualInfo EglContext::selectBestVisual(::Display* XDisplay, unsigned int bitsPerPixel, const ContextSettings& settings) { - ensureInit(); + EglContextImpl::ensureInit(); // Get the initialized EGL display - EGLDisplay display = getInitializedDisplay(); + EGLDisplay display = EglContextImpl::getInitializedDisplay(); // Get the best EGL config matching the default video settings EGLConfig config = getBestConfig(display, bitsPerPixel, settings); diff --git a/src/SFML/Window/GlContext.cpp b/src/SFML/Window/GlContext.cpp index 62dad263c..97ad8af07 100644 --- a/src/SFML/Window/GlContext.cpp +++ b/src/SFML/Window/GlContext.cpp @@ -149,158 +149,162 @@ namespace { - // AMD drivers have issues with internal synchronization - // We need to make sure that no operating system context - // or pixel format operations are performed simultaneously - // This mutex is also used to protect the shared context - // from being locked on multiple threads and for managing - // the resource count - sf::Mutex mutex; - - // OpenGL resources counter - unsigned int resourceCount = 0; - - // This per-thread variable holds the current context for each thread - sf::ThreadLocalPtr currentContext(NULL); - - // The hidden, inactive context that will be shared with all other contexts - ContextType* sharedContext = NULL; - - // Unique identifier, used for identifying contexts when managing unshareable OpenGL resources - sf::Uint64 id = 1; // start at 1, zero is "no context" - - // Set containing callback functions to be called whenever a - // context is going to be destroyed - // Unshareable OpenGL resources rely on this to clean up properly - // whenever a context containing them is destroyed - typedef std::set > ContextDestroyCallbacks; - ContextDestroyCallbacks contextDestroyCallbacks; - - // This structure contains all the state necessary to - // track TransientContext usage - struct TransientContext : private sf::NonCopyable + // A nested named namespace is used here to allow unity builds of SFML. + namespace GlContextImpl { - //////////////////////////////////////////////////////////// - /// \brief Constructor - /// - //////////////////////////////////////////////////////////// - TransientContext() : - referenceCount (0), - context (0), - sharedContextLock(0), - useSharedContext (false) + // AMD drivers have issues with internal synchronization + // We need to make sure that no operating system context + // or pixel format operations are performed simultaneously + // This mutex is also used to protect the shared context + // from being locked on multiple threads and for managing + // the resource count + sf::Mutex mutex; + + // OpenGL resources counter + unsigned int resourceCount = 0; + + // This per-thread variable holds the current context for each thread + sf::ThreadLocalPtr currentContext(NULL); + + // The hidden, inactive context that will be shared with all other contexts + ContextType* sharedContext = NULL; + + // Unique identifier, used for identifying contexts when managing unshareable OpenGL resources + sf::Uint64 id = 1; // start at 1, zero is "no context" + + // Set containing callback functions to be called whenever a + // context is going to be destroyed + // Unshareable OpenGL resources rely on this to clean up properly + // whenever a context containing them is destroyed + typedef std::set > ContextDestroyCallbacks; + ContextDestroyCallbacks contextDestroyCallbacks; + + // This structure contains all the state necessary to + // track TransientContext usage + struct TransientContext : private sf::NonCopyable { - if (resourceCount == 0) + //////////////////////////////////////////////////////////// + /// \brief Constructor + /// + //////////////////////////////////////////////////////////// + TransientContext() : + referenceCount (0), + context (0), + sharedContextLock(0), + useSharedContext (false) { - context = new sf::Context; - } - else if (!currentContext) - { - sharedContextLock = new sf::Lock(mutex); - useSharedContext = true; - sharedContext->setActive(true); - } - } - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~TransientContext() - { - if (useSharedContext) - sharedContext->setActive(false); - - delete sharedContextLock; - delete context; - } - - /////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - unsigned int referenceCount; - sf::Context* context; - sf::Lock* sharedContextLock; - bool useSharedContext; - }; - - // This per-thread variable tracks if and how a transient - // context is currently being used on the current thread - sf::ThreadLocalPtr transientContext(NULL); - - // Supported OpenGL extensions - std::vector extensions; - - // Load our extensions vector with the supported extensions - void loadExtensions() - { - extensions.clear(); - - glGetErrorFuncType glGetErrorFunc = reinterpret_cast(sf::priv::GlContext::getFunction("glGetError")); - glGetIntegervFuncType glGetIntegervFunc = reinterpret_cast(sf::priv::GlContext::getFunction("glGetIntegerv")); - glGetStringFuncType glGetStringFunc = reinterpret_cast(sf::priv::GlContext::getFunction("glGetString")); - - if (!glGetErrorFunc || !glGetIntegervFunc || !glGetStringFunc) - return; - - // Check whether a >= 3.0 context is available - int majorVersion = 0; - glGetIntegervFunc(GL_MAJOR_VERSION, &majorVersion); - - glGetStringiFuncType glGetStringiFunc = reinterpret_cast(sf::priv::GlContext::getFunction("glGetStringi")); - - if (glGetErrorFunc() == GL_INVALID_ENUM || !glGetStringiFunc) - { - // Try to load the < 3.0 way - const char* extensionString = reinterpret_cast(glGetStringFunc(GL_EXTENSIONS)); - - do - { - const char* extension = extensionString; - - while (*extensionString && (*extensionString != ' ')) - extensionString++; - - extensions.push_back(std::string(extension, extensionString)); - } - while (*extensionString++); - } - else - { - // Try to load the >= 3.0 way - int numExtensions = 0; - glGetIntegervFunc(GL_NUM_EXTENSIONS, &numExtensions); - - if (numExtensions) - { - for (unsigned int i = 0; i < static_cast(numExtensions); ++i) + if (resourceCount == 0) { - const char* extensionString = reinterpret_cast(glGetStringiFunc(GL_EXTENSIONS, i)); + context = new sf::Context; + } + else if (!currentContext) + { + sharedContextLock = new sf::Lock(mutex); + useSharedContext = true; + sharedContext->setActive(true); + } + } - extensions.push_back(extensionString); + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~TransientContext() + { + if (useSharedContext) + sharedContext->setActive(false); + + delete sharedContextLock; + delete context; + } + + /////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + unsigned int referenceCount; + sf::Context* context; + sf::Lock* sharedContextLock; + bool useSharedContext; + }; + + // This per-thread variable tracks if and how a transient + // context is currently being used on the current thread + sf::ThreadLocalPtr transientContext(NULL); + + // Supported OpenGL extensions + std::vector extensions; + + // Load our extensions vector with the supported extensions + void loadExtensions() + { + extensions.clear(); + + glGetErrorFuncType glGetErrorFunc = reinterpret_cast(sf::priv::GlContext::getFunction("glGetError")); + glGetIntegervFuncType glGetIntegervFunc = reinterpret_cast(sf::priv::GlContext::getFunction("glGetIntegerv")); + glGetStringFuncType glGetStringFunc = reinterpret_cast(sf::priv::GlContext::getFunction("glGetString")); + + if (!glGetErrorFunc || !glGetIntegervFunc || !glGetStringFunc) + return; + + // Check whether a >= 3.0 context is available + int majorVersion = 0; + glGetIntegervFunc(GL_MAJOR_VERSION, &majorVersion); + + glGetStringiFuncType glGetStringiFunc = reinterpret_cast(sf::priv::GlContext::getFunction("glGetStringi")); + + if (glGetErrorFunc() == GL_INVALID_ENUM || !glGetStringiFunc) + { + // Try to load the < 3.0 way + const char* extensionString = reinterpret_cast(glGetStringFunc(GL_EXTENSIONS)); + + do + { + const char* extension = extensionString; + + while (*extensionString && (*extensionString != ' ')) + extensionString++; + + extensions.push_back(std::string(extension, extensionString)); + } + while (*extensionString++); + } + else + { + // Try to load the >= 3.0 way + int numExtensions = 0; + glGetIntegervFunc(GL_NUM_EXTENSIONS, &numExtensions); + + if (numExtensions) + { + for (unsigned int i = 0; i < static_cast(numExtensions); ++i) + { + const char* extensionString = reinterpret_cast(glGetStringiFunc(GL_EXTENSIONS, i)); + + extensions.push_back(extensionString); + } } } } - } - // Helper to parse OpenGL version strings - bool parseVersionString(const char* version, const char* prefix, unsigned int &major, unsigned int &minor) - { - std::size_t prefixLength = std::strlen(prefix); - - if ((std::strlen(version) >= (prefixLength + 3)) && - (std::strncmp(version, prefix, prefixLength) == 0) && - std::isdigit(version[prefixLength]) && - (version[prefixLength + 1] == '.') && - std::isdigit(version[prefixLength + 2])) + // Helper to parse OpenGL version strings + bool parseVersionString(const char* version, const char* prefix, unsigned int &major, unsigned int &minor) { - major = version[prefixLength] - '0'; - minor = version[prefixLength + 2] - '0'; + std::size_t prefixLength = std::strlen(prefix); - return true; + if ((std::strlen(version) >= (prefixLength + 3)) && + (std::strncmp(version, prefix, prefixLength) == 0) && + std::isdigit(version[prefixLength]) && + (version[prefixLength + 1] == '.') && + std::isdigit(version[prefixLength + 2])) + { + major = version[prefixLength] - '0'; + minor = version[prefixLength + 2] - '0'; + + return true; + } + + return false; } - - return false; } } @@ -312,6 +316,12 @@ namespace priv //////////////////////////////////////////////////////////// void GlContext::initResource() { + using GlContextImpl::mutex; + using GlContextImpl::resourceCount; + using GlContextImpl::currentContext; + using GlContextImpl::sharedContext; + using GlContextImpl::loadExtensions; + // Protect from concurrent access Lock lock(mutex); @@ -345,6 +355,10 @@ void GlContext::initResource() //////////////////////////////////////////////////////////// void GlContext::cleanupResource() { + using GlContextImpl::mutex; + using GlContextImpl::resourceCount; + using GlContextImpl::sharedContext; + // Protect from concurrent access Lock lock(mutex); @@ -367,13 +381,17 @@ void GlContext::cleanupResource() //////////////////////////////////////////////////////////// void GlContext::registerContextDestroyCallback(ContextDestroyCallback callback, void* arg) { - contextDestroyCallbacks.insert(std::make_pair(callback, arg)); + GlContextImpl::contextDestroyCallbacks.insert(std::make_pair(callback, arg)); } //////////////////////////////////////////////////////////// void GlContext::acquireTransientContext() { + using GlContextImpl::mutex; + using GlContextImpl::TransientContext; + using GlContextImpl::transientContext; + // Protect from concurrent access Lock lock(mutex); @@ -390,6 +408,9 @@ void GlContext::acquireTransientContext() //////////////////////////////////////////////////////////// void GlContext::releaseTransientContext() { + using GlContextImpl::mutex; + using GlContextImpl::transientContext; + // Protect from concurrent access Lock lock(mutex); @@ -412,6 +433,9 @@ void GlContext::releaseTransientContext() //////////////////////////////////////////////////////////// GlContext* GlContext::create() { + using GlContextImpl::mutex; + using GlContextImpl::sharedContext; + // Make sure that there's an active context (context creation may need extensions, and thus a valid context) assert(sharedContext != NULL); @@ -440,6 +464,11 @@ GlContext* GlContext::create() //////////////////////////////////////////////////////////// GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) { + using GlContextImpl::mutex; + using GlContextImpl::resourceCount; + using GlContextImpl::sharedContext; + using GlContextImpl::loadExtensions; + // Make sure that there's an active context (context creation may need extensions, and thus a valid context) assert(sharedContext != NULL); @@ -488,6 +517,11 @@ GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl* //////////////////////////////////////////////////////////// GlContext* GlContext::create(const ContextSettings& settings, unsigned int width, unsigned int height) { + using GlContextImpl::mutex; + using GlContextImpl::resourceCount; + using GlContextImpl::sharedContext; + using GlContextImpl::loadExtensions; + // Make sure that there's an active context (context creation may need extensions, and thus a valid context) assert(sharedContext != NULL); @@ -536,6 +570,7 @@ GlContext* GlContext::create(const ContextSettings& settings, unsigned int width //////////////////////////////////////////////////////////// bool GlContext::isExtensionAvailable(const char* name) { + using GlContextImpl::extensions; return std::find(extensions.begin(), extensions.end(), name) != extensions.end(); } @@ -543,7 +578,7 @@ bool GlContext::isExtensionAvailable(const char* name) //////////////////////////////////////////////////////////// GlFunctionPointer GlContext::getFunction(const char* name) { - Lock lock(mutex); + Lock lock(GlContextImpl::mutex); return ContextType::getFunction(name); } @@ -552,6 +587,7 @@ GlFunctionPointer GlContext::getFunction(const char* name) //////////////////////////////////////////////////////////// const GlContext* GlContext::getActiveContext() { + using GlContextImpl::currentContext; return currentContext; } @@ -559,6 +595,7 @@ const GlContext* GlContext::getActiveContext() //////////////////////////////////////////////////////////// Uint64 GlContext::getActiveContextId() { + using GlContextImpl::currentContext; return currentContext ? currentContext->m_id : 0; } @@ -566,6 +603,9 @@ Uint64 GlContext::getActiveContextId() //////////////////////////////////////////////////////////// GlContext::~GlContext() { + using GlContextImpl::currentContext; + using GlContextImpl::sharedContext; + // Deactivate the context before killing it, unless we're inside Cleanup() if (sharedContext) { @@ -585,6 +625,10 @@ const ContextSettings& GlContext::getSettings() const //////////////////////////////////////////////////////////// bool GlContext::setActive(bool active) { + using GlContextImpl::mutex; + using GlContextImpl::currentContext; + using GlContextImpl::sharedContext; + if (active) { if (this != currentContext) @@ -637,7 +681,7 @@ bool GlContext::setActive(bool active) //////////////////////////////////////////////////////////// GlContext::GlContext() : -m_id(id++) +m_id(GlContextImpl::id++) { // Nothing to do } @@ -675,6 +719,10 @@ int GlContext::evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& //////////////////////////////////////////////////////////// void GlContext::cleanupUnsharedResources() { + using GlContextImpl::currentContext; + using GlContextImpl::ContextDestroyCallbacks; + using GlContextImpl::contextDestroyCallbacks; + // Save the current context so we can restore it later GlContext* contextToRestore = currentContext; @@ -742,6 +790,8 @@ void GlContext::initialize(const ContextSettings& requestedSettings) // OpenGL ES Full profile: The beginning of the returned string is "OpenGL ES major.minor" // Desktop OpenGL: The beginning of the returned string is "major.minor" + using GlContextImpl::parseVersionString; + if (!parseVersionString(version, "OpenGL ES-CL ", m_settings.majorVersion, m_settings.minorVersion) && !parseVersionString(version, "OpenGL ES-CM ", m_settings.majorVersion, m_settings.minorVersion) && !parseVersionString(version, "OpenGL ES ", m_settings.majorVersion, m_settings.minorVersion) && diff --git a/src/SFML/Window/Unix/GlxContext.cpp b/src/SFML/Window/Unix/GlxContext.cpp index 24455c842..12be10925 100644 --- a/src/SFML/Window/Unix/GlxContext.cpp +++ b/src/SFML/Window/Unix/GlxContext.cpp @@ -25,7 +25,6 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#define SF_GLAD_GLX_IMPLEMENTATION #include // important to be included first (conflict with None) #include #include @@ -34,6 +33,14 @@ #include #include +// We check for this definition in order to avoid multiple definitions of GLAD +// entities during unity builds of SFML. +#ifndef SF_GLAD_GLX_IMPLEMENTATION_INCLUDED +#define SF_GLAD_GLX_IMPLEMENTATION_INCLUDED +#define SF_GLAD_GLX_IMPLEMENTATION +#include +#endif + #if !defined(GLX_DEBUGGING) && defined(SFML_DEBUG) // Enable this to print messages to err() everytime GLX produces errors //#define GLX_DEBUGGING @@ -52,7 +59,7 @@ namespace if (!initialized) { initialized = true; - + // We don't check the return value since the extension // flags are cleared even if loading fails gladLoaderLoadGLX(display, screen); diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 36b2f1b19..ef1f8ec99 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -62,105 +62,140 @@ //////////////////////////////////////////////////////////// namespace { - sf::priv::WindowImplX11* fullscreenWindow = NULL; - std::vector allWindows; - sf::Mutex allWindowsMutex; - sf::String windowManagerName; - - sf::String wmAbsPosGood[] = { "Enlightenment", "FVWM", "i3" }; - - static const unsigned long eventMask = FocusChangeMask | ButtonPressMask | - ButtonReleaseMask | ButtonMotionMask | - PointerMotionMask | KeyPressMask | - KeyReleaseMask | StructureNotifyMask | - EnterWindowMask | LeaveWindowMask | - VisibilityChangeMask | PropertyChangeMask; - - static const unsigned int maxTrialsCount = 5; - - // Predicate we use to find key repeat events in processEvent - struct KeyRepeatFinder + // A nested named namespace is used here to allow unity builds of SFML. + namespace WindowsImplX11Impl { - KeyRepeatFinder(unsigned int keycode, Time time) : keycode(keycode), time(time) {} + sf::priv::WindowImplX11* fullscreenWindow = NULL; + std::vector allWindows; + sf::Mutex allWindowsMutex; + sf::String windowManagerName; - // Predicate operator that checks event type, keycode and timestamp - bool operator()(const XEvent& event) + sf::String wmAbsPosGood[] = { "Enlightenment", "FVWM", "i3" }; + + static const unsigned long eventMask = FocusChangeMask | ButtonPressMask | + ButtonReleaseMask | ButtonMotionMask | + PointerMotionMask | KeyPressMask | + KeyReleaseMask | StructureNotifyMask | + EnterWindowMask | LeaveWindowMask | + VisibilityChangeMask | PropertyChangeMask; + + static const unsigned int maxTrialsCount = 5; + + // Predicate we use to find key repeat events in processEvent + struct KeyRepeatFinder { - return ((event.type == KeyPress) && (event.xkey.keycode == keycode) && (event.xkey.time - time < 2)); + KeyRepeatFinder(unsigned int keycode, Time time) : keycode(keycode), time(time) {} + + // Predicate operator that checks event type, keycode and timestamp + bool operator()(const XEvent& event) + { + return ((event.type == KeyPress) && (event.xkey.keycode == keycode) && (event.xkey.time - time < 2)); + } + + unsigned int keycode; + Time time; + }; + + // Filter the events received by windows (only allow those matching a specific window) + Bool checkEvent(::Display*, XEvent* event, XPointer userData) + { + // Just check if the event matches the window + return event->xany.window == reinterpret_cast< ::Window >(userData); } - unsigned int keycode; - Time time; - }; + // Find the name of the current executable + std::string findExecutableName() + { + // We use /proc/self/cmdline to get the command line + // the user used to invoke this instance of the application + int file = ::open("/proc/self/cmdline", O_RDONLY | O_NONBLOCK); - // 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); - } + if (file < 0) + return "sfml"; - // Find the name of the current executable - std::string findExecutableName() - { - // We use /proc/self/cmdline to get the command line - // the user used to invoke this instance of the application - int file = ::open("/proc/self/cmdline", O_RDONLY | O_NONBLOCK); + std::vector buffer(256, 0); + std::size_t offset = 0; + ssize_t result = 0; - if (file < 0) + while ((result = read(file, &buffer[offset], 256)) > 0) + { + buffer.resize(buffer.size() + result, 0); + offset += result; + } + + ::close(file); + + if (offset) + { + buffer[offset] = 0; + + // Remove the path to keep the executable name only + return basename(&buffer[0]); + } + + // Default fallback name return "sfml"; - - std::vector buffer(256, 0); - std::size_t offset = 0; - ssize_t result = 0; - - while ((result = read(file, &buffer[offset], 256)) > 0) - { - buffer.resize(buffer.size() + result, 0); - offset += result; } - ::close(file); - - if (offset) + // Check if Extended Window Manager Hints are supported + bool ewmhSupported() { - buffer[offset] = 0; + static bool checked = false; + static bool ewmhSupported = false; - // Remove the path to keep the executable name only - return basename(&buffer[0]); - } + if (checked) + return ewmhSupported; - // Default fallback name - return "sfml"; - } + checked = true; - // Check if Extended Window Manager Hints are supported - bool ewmhSupported() - { - static bool checked = false; - static bool ewmhSupported = false; + Atom netSupportingWmCheck = sf::priv::getAtom("_NET_SUPPORTING_WM_CHECK", true); + Atom netSupported = sf::priv::getAtom("_NET_SUPPORTED", true); - if (checked) - return ewmhSupported; + if (!netSupportingWmCheck || !netSupported) + return false; - checked = true; + ::Display* display = sf::priv::OpenDisplay(); - Atom netSupportingWmCheck = sf::priv::getAtom("_NET_SUPPORTING_WM_CHECK", true); - Atom netSupported = sf::priv::getAtom("_NET_SUPPORTED", true); + Atom actualType; + int actualFormat; + unsigned long numItems; + unsigned long numBytes; + unsigned char* data; - if (!netSupportingWmCheck || !netSupported) - return false; + int result = XGetWindowProperty(display, + DefaultRootWindow(display), + netSupportingWmCheck, + 0, + 1, + False, + XA_WINDOW, + &actualType, + &actualFormat, + &numItems, + &numBytes, + &data); - ::Display* display = sf::priv::OpenDisplay(); + if (result != Success || actualType != XA_WINDOW || numItems != 1) + { + if (result == Success) + XFree(data); - Atom actualType; - int actualFormat; - unsigned long numItems; - unsigned long numBytes; - unsigned char* data; + sf::priv::CloseDisplay(display); + return false; + } - int result = XGetWindowProperty(display, - DefaultRootWindow(display), + ::Window rootWindow = *reinterpret_cast< ::Window* >(data); + + XFree(data); + + if (!rootWindow) + { + sf::priv::CloseDisplay(display); + return false; + } + + result = XGetWindowProperty(display, + rootWindow, netSupportingWmCheck, 0, 1, @@ -172,305 +207,274 @@ namespace &numBytes, &data); - if (result != Success || actualType != XA_WINDOW || numItems != 1) - { - if (result == Success) - XFree(data); + if (result != Success || actualType != XA_WINDOW || numItems != 1) + { + if (result == Success) + XFree(data); - sf::priv::CloseDisplay(display); - return false; - } + sf::priv::CloseDisplay(display); + return false; + } - ::Window rootWindow = *reinterpret_cast< ::Window* >(data); + ::Window childWindow = *reinterpret_cast< ::Window* >(data); - XFree(data); - - if (!rootWindow) - { - sf::priv::CloseDisplay(display); - return false; - } - - result = XGetWindowProperty(display, - rootWindow, - netSupportingWmCheck, - 0, - 1, - False, - XA_WINDOW, - &actualType, - &actualFormat, - &numItems, - &numBytes, - &data); - - if (result != Success || actualType != XA_WINDOW || numItems != 1) - { - if (result == Success) - XFree(data); - - sf::priv::CloseDisplay(display); - return false; - } - - ::Window childWindow = *reinterpret_cast< ::Window* >(data); - - XFree(data); - - if (!childWindow) - { - sf::priv::CloseDisplay(display); - return false; - } - - // Conforming window managers should return the same window for both queries - if (rootWindow != childWindow) - { - sf::priv::CloseDisplay(display); - return false; - } - - ewmhSupported = true; - - // We try to get the name of the window manager - // for window manager specific workarounds - Atom netWmName = sf::priv::getAtom("_NET_WM_NAME", true); - - if (!netWmName) - { - sf::priv::CloseDisplay(display); - return true; - } - - Atom utf8StringType = sf::priv::getAtom("UTF8_STRING"); - - if (!utf8StringType) - utf8StringType = XA_STRING; - - result = XGetWindowProperty(display, - rootWindow, - netWmName, - 0, - 0x7fffffff, - False, - utf8StringType, - &actualType, - &actualFormat, - &numItems, - &numBytes, - &data); - - if (actualType && numItems) - { - // 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(data); - const char* end = begin + numItems; - windowManagerName = sf::String::fromUtf8(begin, end); - } - - if (result == Success) XFree(data); - sf::priv::CloseDisplay(display); + if (!childWindow) + { + sf::priv::CloseDisplay(display); + return false; + } - return true; - } + // Conforming window managers should return the same window for both queries + if (rootWindow != childWindow) + { + sf::priv::CloseDisplay(display); + return false; + } - // Get the parent window. - ::Window getParentWindow(::Display* disp, ::Window win) - { - ::Window root, parent; - ::Window* children = NULL; - unsigned int numChildren; + ewmhSupported = true; - XQueryTree(disp, win, &root, &parent, &children, &numChildren); + // We try to get the name of the window manager + // for window manager specific workarounds + Atom netWmName = sf::priv::getAtom("_NET_WM_NAME", true); - // Children information is not used, so must be freed. - if (children != NULL) - XFree(children); + if (!netWmName) + { + sf::priv::CloseDisplay(display); + return true; + } - return parent; - } + Atom utf8StringType = sf::priv::getAtom("UTF8_STRING"); - // Get the Frame Extents from EWMH WMs that support it. - bool getEWMHFrameExtents(::Display* disp, ::Window win, - long& xFrameExtent, long& yFrameExtent) - { - if (!ewmhSupported()) - return false; + if (!utf8StringType) + utf8StringType = XA_STRING; - Atom frameExtents = sf::priv::getAtom("_NET_FRAME_EXTENTS", true); - - if (frameExtents == None) - return false; - - bool gotFrameExtents = false; - Atom actualType; - int actualFormat; - unsigned long numItems; - unsigned long numBytesLeft; - unsigned char* data = NULL; - - int result = XGetWindowProperty(disp, - win, - frameExtents, + result = XGetWindowProperty(display, + rootWindow, + netWmName, 0, - 4, + 0x7fffffff, False, - XA_CARDINAL, + utf8StringType, &actualType, &actualFormat, &numItems, - &numBytesLeft, + &numBytes, &data); - if ((result == Success) && (actualType == XA_CARDINAL) && - (actualFormat == 32) && (numItems == 4) && (numBytesLeft == 0) && - (data != NULL)) - { - gotFrameExtents = true; + if (actualType && numItems) + { + // 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(data); + const char* end = begin + numItems; + windowManagerName = sf::String::fromUtf8(begin, end); + } - long* extents = (long*) data; + if (result == Success) + XFree(data); - xFrameExtent = extents[0]; // Left. - yFrameExtent = extents[2]; // Top. + sf::priv::CloseDisplay(display); + + return true; } - // Always free data. - if (data != NULL) - XFree(data); + // Get the parent window. + ::Window getParentWindow(::Display* disp, ::Window win) + { + ::Window root, parent; + ::Window* children = NULL; + unsigned int numChildren; - return gotFrameExtents; - } + XQueryTree(disp, win, &root, &parent, &children, &numChildren); + + // Children information is not used, so must be freed. + if (children != NULL) + XFree(children); + + return parent; + } + + // Get the Frame Extents from EWMH WMs that support it. + bool getEWMHFrameExtents(::Display* disp, ::Window win, + long& xFrameExtent, long& yFrameExtent) + { + if (!ewmhSupported()) + return false; + + Atom frameExtents = sf::priv::getAtom("_NET_FRAME_EXTENTS", true); + + if (frameExtents == None) + return false; + + bool gotFrameExtents = false; + Atom actualType; + int actualFormat; + unsigned long numItems; + unsigned long numBytesLeft; + unsigned char* data = NULL; + + int result = XGetWindowProperty(disp, + win, + frameExtents, + 0, + 4, + False, + XA_CARDINAL, + &actualType, + &actualFormat, + &numItems, + &numBytesLeft, + &data); + + if ((result == Success) && (actualType == XA_CARDINAL) && + (actualFormat == 32) && (numItems == 4) && (numBytesLeft == 0) && + (data != NULL)) + { + gotFrameExtents = true; + + long* extents = (long*) data; + + xFrameExtent = extents[0]; // Left. + yFrameExtent = extents[2]; // Top. + } + + // Always free data. + if (data != NULL) + XFree(data); + + return gotFrameExtents; + } + + // Check if the current WM is in the list of good WMs that provide + // a correct absolute position for the window when queried. + bool isWMAbsolutePositionGood() + { + // This can only work with EWMH, to get the name. + if (!ewmhSupported()) + return false; + + for (size_t i = 0; i < (sizeof(wmAbsPosGood) / sizeof(wmAbsPosGood[0])); i++) + { + if (wmAbsPosGood[i] == windowManagerName) + return true; + } - // Check if the current WM is in the list of good WMs that provide - // a correct absolute position for the window when queried. - bool isWMAbsolutePositionGood() - { - // This can only work with EWMH, to get the name. - if (!ewmhSupported()) return false; - - for (size_t i = 0; i < (sizeof(wmAbsPosGood) / sizeof(wmAbsPosGood[0])); i++) - { - if (wmAbsPosGood[i] == windowManagerName) - return true; } - return false; - } - - sf::Keyboard::Key keysymToSF(KeySym symbol) - { - switch (symbol) + sf::Keyboard::Key keysymToSF(KeySym symbol) { - case XK_Shift_L: return sf::Keyboard::LShift; - case XK_Shift_R: return sf::Keyboard::RShift; - case XK_Control_L: return sf::Keyboard::LControl; - case XK_Control_R: return sf::Keyboard::RControl; - case XK_Alt_L: return sf::Keyboard::LAlt; - case XK_Alt_R: return sf::Keyboard::RAlt; - case XK_Super_L: return sf::Keyboard::LSystem; - case XK_Super_R: return sf::Keyboard::RSystem; - case XK_Menu: return sf::Keyboard::Menu; - case XK_Escape: return sf::Keyboard::Escape; - case XK_semicolon: return sf::Keyboard::Semicolon; - case XK_slash: return sf::Keyboard::Slash; - case XK_equal: return sf::Keyboard::Equal; - case XK_minus: return sf::Keyboard::Hyphen; - case XK_bracketleft: return sf::Keyboard::LBracket; - case XK_bracketright: return sf::Keyboard::RBracket; - case XK_comma: return sf::Keyboard::Comma; - case XK_period: return sf::Keyboard::Period; - case XK_apostrophe: return sf::Keyboard::Quote; - case XK_backslash: return sf::Keyboard::Backslash; - case XK_grave: return sf::Keyboard::Tilde; - case XK_space: return sf::Keyboard::Space; - case XK_Return: return sf::Keyboard::Enter; - case XK_KP_Enter: return sf::Keyboard::Enter; - case XK_BackSpace: return sf::Keyboard::Backspace; - case XK_Tab: return sf::Keyboard::Tab; - case XK_Prior: return sf::Keyboard::PageUp; - case XK_Next: return sf::Keyboard::PageDown; - case XK_End: return sf::Keyboard::End; - case XK_Home: return sf::Keyboard::Home; - case XK_Insert: return sf::Keyboard::Insert; - case XK_Delete: return sf::Keyboard::Delete; - case XK_KP_Add: return sf::Keyboard::Add; - case XK_KP_Subtract: return sf::Keyboard::Subtract; - case XK_KP_Multiply: return sf::Keyboard::Multiply; - case XK_KP_Divide: return sf::Keyboard::Divide; - case XK_Pause: return sf::Keyboard::Pause; - case XK_F1: return sf::Keyboard::F1; - case XK_F2: return sf::Keyboard::F2; - case XK_F3: return sf::Keyboard::F3; - case XK_F4: return sf::Keyboard::F4; - case XK_F5: return sf::Keyboard::F5; - case XK_F6: return sf::Keyboard::F6; - case XK_F7: return sf::Keyboard::F7; - case XK_F8: return sf::Keyboard::F8; - case XK_F9: return sf::Keyboard::F9; - case XK_F10: return sf::Keyboard::F10; - case XK_F11: return sf::Keyboard::F11; - case XK_F12: return sf::Keyboard::F12; - case XK_F13: return sf::Keyboard::F13; - case XK_F14: return sf::Keyboard::F14; - case XK_F15: return sf::Keyboard::F15; - case XK_Left: return sf::Keyboard::Left; - case XK_Right: return sf::Keyboard::Right; - case XK_Up: return sf::Keyboard::Up; - case XK_Down: return sf::Keyboard::Down; - 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; - case XK_d: return sf::Keyboard::D; - case XK_e: return sf::Keyboard::E; - case XK_f: return sf::Keyboard::F; - case XK_g: return sf::Keyboard::G; - case XK_h: return sf::Keyboard::H; - case XK_i: return sf::Keyboard::I; - case XK_j: return sf::Keyboard::J; - case XK_k: return sf::Keyboard::K; - case XK_l: return sf::Keyboard::L; - case XK_m: return sf::Keyboard::M; - case XK_n: return sf::Keyboard::N; - case XK_o: return sf::Keyboard::O; - case XK_p: return sf::Keyboard::P; - case XK_q: return sf::Keyboard::Q; - case XK_r: return sf::Keyboard::R; - case XK_s: return sf::Keyboard::S; - case XK_t: return sf::Keyboard::T; - case XK_u: return sf::Keyboard::U; - case XK_v: return sf::Keyboard::V; - case XK_w: return sf::Keyboard::W; - case XK_x: return sf::Keyboard::X; - case XK_y: return sf::Keyboard::Y; - case XK_z: return sf::Keyboard::Z; - case XK_0: return sf::Keyboard::Num0; - case XK_1: return sf::Keyboard::Num1; - case XK_2: return sf::Keyboard::Num2; - case XK_3: return sf::Keyboard::Num3; - case XK_4: return sf::Keyboard::Num4; - case XK_5: return sf::Keyboard::Num5; - case XK_6: return sf::Keyboard::Num6; - case XK_7: return sf::Keyboard::Num7; - case XK_8: return sf::Keyboard::Num8; - case XK_9: return sf::Keyboard::Num9; - } + switch (symbol) + { + case XK_Shift_L: return sf::Keyboard::LShift; + case XK_Shift_R: return sf::Keyboard::RShift; + case XK_Control_L: return sf::Keyboard::LControl; + case XK_Control_R: return sf::Keyboard::RControl; + case XK_Alt_L: return sf::Keyboard::LAlt; + case XK_Alt_R: return sf::Keyboard::RAlt; + case XK_Super_L: return sf::Keyboard::LSystem; + case XK_Super_R: return sf::Keyboard::RSystem; + case XK_Menu: return sf::Keyboard::Menu; + case XK_Escape: return sf::Keyboard::Escape; + case XK_semicolon: return sf::Keyboard::Semicolon; + case XK_slash: return sf::Keyboard::Slash; + case XK_equal: return sf::Keyboard::Equal; + case XK_minus: return sf::Keyboard::Hyphen; + case XK_bracketleft: return sf::Keyboard::LBracket; + case XK_bracketright: return sf::Keyboard::RBracket; + case XK_comma: return sf::Keyboard::Comma; + case XK_period: return sf::Keyboard::Period; + case XK_apostrophe: return sf::Keyboard::Quote; + case XK_backslash: return sf::Keyboard::Backslash; + case XK_grave: return sf::Keyboard::Tilde; + case XK_space: return sf::Keyboard::Space; + case XK_Return: return sf::Keyboard::Enter; + case XK_KP_Enter: return sf::Keyboard::Enter; + case XK_BackSpace: return sf::Keyboard::Backspace; + case XK_Tab: return sf::Keyboard::Tab; + case XK_Prior: return sf::Keyboard::PageUp; + case XK_Next: return sf::Keyboard::PageDown; + case XK_End: return sf::Keyboard::End; + case XK_Home: return sf::Keyboard::Home; + case XK_Insert: return sf::Keyboard::Insert; + case XK_Delete: return sf::Keyboard::Delete; + case XK_KP_Add: return sf::Keyboard::Add; + case XK_KP_Subtract: return sf::Keyboard::Subtract; + case XK_KP_Multiply: return sf::Keyboard::Multiply; + case XK_KP_Divide: return sf::Keyboard::Divide; + case XK_Pause: return sf::Keyboard::Pause; + case XK_F1: return sf::Keyboard::F1; + case XK_F2: return sf::Keyboard::F2; + case XK_F3: return sf::Keyboard::F3; + case XK_F4: return sf::Keyboard::F4; + case XK_F5: return sf::Keyboard::F5; + case XK_F6: return sf::Keyboard::F6; + case XK_F7: return sf::Keyboard::F7; + case XK_F8: return sf::Keyboard::F8; + case XK_F9: return sf::Keyboard::F9; + case XK_F10: return sf::Keyboard::F10; + case XK_F11: return sf::Keyboard::F11; + case XK_F12: return sf::Keyboard::F12; + case XK_F13: return sf::Keyboard::F13; + case XK_F14: return sf::Keyboard::F14; + case XK_F15: return sf::Keyboard::F15; + case XK_Left: return sf::Keyboard::Left; + case XK_Right: return sf::Keyboard::Right; + case XK_Up: return sf::Keyboard::Up; + case XK_Down: return sf::Keyboard::Down; + 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; + case XK_d: return sf::Keyboard::D; + case XK_e: return sf::Keyboard::E; + case XK_f: return sf::Keyboard::F; + case XK_g: return sf::Keyboard::G; + case XK_h: return sf::Keyboard::H; + case XK_i: return sf::Keyboard::I; + case XK_j: return sf::Keyboard::J; + case XK_k: return sf::Keyboard::K; + case XK_l: return sf::Keyboard::L; + case XK_m: return sf::Keyboard::M; + case XK_n: return sf::Keyboard::N; + case XK_o: return sf::Keyboard::O; + case XK_p: return sf::Keyboard::P; + case XK_q: return sf::Keyboard::Q; + case XK_r: return sf::Keyboard::R; + case XK_s: return sf::Keyboard::S; + case XK_t: return sf::Keyboard::T; + case XK_u: return sf::Keyboard::U; + case XK_v: return sf::Keyboard::V; + case XK_w: return sf::Keyboard::W; + case XK_x: return sf::Keyboard::X; + case XK_y: return sf::Keyboard::Y; + case XK_z: return sf::Keyboard::Z; + case XK_0: return sf::Keyboard::Num0; + case XK_1: return sf::Keyboard::Num1; + case XK_2: return sf::Keyboard::Num2; + case XK_3: return sf::Keyboard::Num3; + case XK_4: return sf::Keyboard::Num4; + case XK_5: return sf::Keyboard::Num5; + case XK_6: return sf::Keyboard::Num6; + case XK_7: return sf::Keyboard::Num7; + case XK_8: return sf::Keyboard::Num8; + case XK_9: return sf::Keyboard::Num9; + } - return sf::Keyboard::Unknown; + return sf::Keyboard::Unknown; + } } } @@ -500,6 +504,8 @@ m_iconPixmap (0), m_iconMaskPixmap (0), m_lastInputTime (0) { + using namespace WindowsImplX11Impl; + // Open a connection with the X server m_display = OpenDisplay(); @@ -549,6 +555,8 @@ m_iconPixmap (0), m_iconMaskPixmap (0), m_lastInputTime (0) { + using namespace WindowsImplX11Impl; + // Open a connection with the X server m_display = OpenDisplay(); @@ -745,7 +753,7 @@ m_lastInputTime (0) sizeHints->flags &= ~(PMinSize | PMaxSize); XSetWMNormalHints(m_display, m_window, sizeHints); XFree(sizeHints); - + setVideoMode(mode); switchToFullscreen(); } @@ -755,6 +763,8 @@ m_lastInputTime (0) //////////////////////////////////////////////////////////// WindowImplX11::~WindowImplX11() { + using namespace WindowsImplX11Impl; + // Cleanup graphical resources cleanup(); @@ -804,6 +814,8 @@ WindowHandle WindowImplX11::getSystemHandle() const //////////////////////////////////////////////////////////// void WindowImplX11::processEvents() { + using namespace WindowsImplX11Impl; + XEvent event; // Pick out the events that are interesting for this window @@ -826,6 +838,8 @@ void WindowImplX11::processEvents() //////////////////////////////////////////////////////////// Vector2i WindowImplX11::getPosition() const { + using namespace WindowsImplX11Impl; + // Get absolute position of our window relative to root window. This // takes into account all information that X11 has, including X11 // border widths and any decorations. It corresponds to where the @@ -1119,6 +1133,8 @@ void WindowImplX11::setMouseCursor(const CursorImpl& cursor) //////////////////////////////////////////////////////////// void WindowImplX11::setMouseCursorGrabbed(bool grabbed) { + using namespace WindowsImplX11Impl; + // This has no effect in fullscreen mode if (m_fullscreen || (m_cursorGrabbed == grabbed)) return; @@ -1162,6 +1178,8 @@ void WindowImplX11::setKeyRepeatEnabled(bool enabled) //////////////////////////////////////////////////////////// void WindowImplX11::requestFocus() { + using namespace WindowsImplX11Impl; + // Focus is only stolen among SFML windows, not between applications // Check the global list of windows to find out whether an SFML window has the focus // Note: can't handle console and other non-SFML windows belonging to the application. @@ -1226,6 +1244,8 @@ bool WindowImplX11::hasFocus() const //////////////////////////////////////////////////////////// void WindowImplX11::grabFocus() { + using namespace WindowsImplX11Impl; + Atom netActiveWindow = None; if (ewmhSupported()) @@ -1275,6 +1295,8 @@ void WindowImplX11::grabFocus() //////////////////////////////////////////////////////////// void WindowImplX11::setVideoMode(const VideoMode& mode) { + using namespace WindowsImplX11Impl; + // Skip mode switching if the new mode is equal to the desktop mode if (mode == VideoMode::getDesktopMode()) return; @@ -1379,6 +1401,8 @@ void WindowImplX11::setVideoMode(const VideoMode& mode) //////////////////////////////////////////////////////////// void WindowImplX11::resetVideoMode() { + using namespace WindowsImplX11Impl; + if (fullscreenWindow == this) { // Try to set old configuration @@ -1441,6 +1465,8 @@ void WindowImplX11::resetVideoMode() //////////////////////////////////////////////////////////// void WindowImplX11::switchToFullscreen() { + using namespace WindowsImplX11Impl; + grabFocus(); if (ewmhSupported()) @@ -1497,6 +1523,8 @@ void WindowImplX11::switchToFullscreen() //////////////////////////////////////////////////////////// void WindowImplX11::setProtocols() { + using namespace WindowsImplX11Impl; + Atom wmProtocols = getAtom("WM_PROTOCOLS"); Atom wmDeleteWindow = getAtom("WM_DELETE_WINDOW"); @@ -1563,6 +1591,8 @@ void WindowImplX11::setProtocols() //////////////////////////////////////////////////////////// void WindowImplX11::initialize() { + using namespace WindowsImplX11Impl; + // Create the input context m_inputMethod = XOpenIM(m_display, NULL, NULL, NULL); @@ -1676,6 +1706,8 @@ void WindowImplX11::cleanup() //////////////////////////////////////////////////////////// bool WindowImplX11::processEvent(XEvent& windowEvent) { + using namespace WindowsImplX11Impl; + // 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 diff --git a/src/SFML/Window/Win32/VulkanImplWin32.cpp b/src/SFML/Window/Win32/VulkanImplWin32.cpp index b46382013..d6b1f602e 100644 --- a/src/SFML/Window/Win32/VulkanImplWin32.cpp +++ b/src/SFML/Window/Win32/VulkanImplWin32.cpp @@ -26,7 +26,9 @@ // Headers //////////////////////////////////////////////////////////// #include +#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN +#endif #include #define VK_USE_PLATFORM_WIN32_KHR #define VK_NO_PROTOTYPES diff --git a/src/SFML/Window/Win32/WglContext.cpp b/src/SFML/Window/Win32/WglContext.cpp index ea8001fc5..09d306d6e 100644 --- a/src/SFML/Window/Win32/WglContext.cpp +++ b/src/SFML/Window/Win32/WglContext.cpp @@ -25,7 +25,6 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#define SF_GLAD_WGL_IMPLEMENTATION #include // included first to avoid a warning about macro redefinition #include #include @@ -35,38 +34,48 @@ #include #include +// We check for this definition in order to avoid multiple definitions of GLAD +// entities during unity builds of SFML. +#ifndef SF_GLAD_WGL_IMPLEMENTATION_INCLUDED +#define SF_GLAD_WGL_IMPLEMENTATION_INCLUDED +#define SF_GLAD_WGL_IMPLEMENTATION +#include +#endif namespace { - // Some drivers are bugged and don't track the current HDC/HGLRC properly - // In order to deactivate successfully, we need to track it ourselves as well - sf::ThreadLocalPtr currentContext(NULL); - - - //////////////////////////////////////////////////////////// - void ensureInit() + namespace WglContextImpl { - static bool initialized = false; - if (!initialized) - { - initialized = true; + // Some drivers are bugged and don't track the current HDC/HGLRC properly + // In order to deactivate successfully, we need to track it ourselves as well + sf::ThreadLocalPtr currentContext(NULL); - gladLoadWGL(NULL, sf::priv::WglContext::getFunction); + + //////////////////////////////////////////////////////////// + void ensureInit() + { + static bool initialized = false; + if (!initialized) + { + initialized = true; + + gladLoadWGL(NULL, sf::priv::WglContext::getFunction); + } } - } - //////////////////////////////////////////////////////////// - void ensureExtensionsInit(HDC deviceContext) - { - static bool initialized = false; - if (!initialized) + //////////////////////////////////////////////////////////// + void ensureExtensionsInit(HDC deviceContext) { - initialized = true; + static bool initialized = false; + if (!initialized) + { + initialized = true; - // We don't check the return value since the extension - // flags are cleared even if loading fails - gladLoadWGL(deviceContext, sf::priv::WglContext::getFunction); + // We don't check the return value since the extension + // flags are cleared even if loading fails + gladLoadWGL(deviceContext, sf::priv::WglContext::getFunction); + } } } } @@ -101,7 +110,7 @@ m_deviceContext(NULL), m_context (NULL), m_ownsWindow (false) { - ensureInit(); + WglContextImpl::ensureInit(); // TODO: Delegate to the other constructor in C++11 @@ -124,7 +133,7 @@ m_deviceContext(NULL), m_context (NULL), m_ownsWindow (false) { - ensureInit(); + WglContextImpl::ensureInit(); // Save the creation settings m_settings = settings; @@ -145,7 +154,7 @@ m_deviceContext(NULL), m_context (NULL), m_ownsWindow (false) { - ensureInit(); + WglContextImpl::ensureInit(); // Save the creation settings m_settings = settings; @@ -167,10 +176,10 @@ WglContext::~WglContext() // Destroy the OpenGL context if (m_context) { - if (currentContext == this) + if (WglContextImpl::currentContext == this) { if (wglMakeCurrent(m_deviceContext, NULL) == TRUE) - currentContext = NULL; + WglContextImpl::currentContext = NULL; } wglDeleteContext(m_context); @@ -234,7 +243,7 @@ bool WglContext::makeCurrent(bool current) return false; } - currentContext = (current ? this : NULL); + WglContextImpl::currentContext = (current ? this : NULL); return true; } @@ -252,7 +261,7 @@ void WglContext::display() void WglContext::setVerticalSyncEnabled(bool enabled) { // Make sure that extensions are initialized - ensureExtensionsInit(m_deviceContext); + WglContextImpl::ensureExtensionsInit(m_deviceContext); if (SF_GLAD_WGL_EXT_swap_control) { @@ -277,7 +286,7 @@ void WglContext::setVerticalSyncEnabled(bool enabled) //////////////////////////////////////////////////////////// int WglContext::selectBestPixelFormat(HDC deviceContext, unsigned int bitsPerPixel, const ContextSettings& settings, bool pbuffer) { - ensureInit(); + WglContextImpl::ensureInit(); // Let's find a suitable pixel format -- first try with wglChoosePixelFormatARB int bestFormat = 0; @@ -658,7 +667,7 @@ void WglContext::createContext(WglContext* shared) static Mutex mutex; Lock lock(mutex); - if (currentContext == shared) + if (WglContextImpl::currentContext == shared) { if (wglMakeCurrent(shared->m_deviceContext, NULL) == FALSE) { @@ -666,7 +675,7 @@ void WglContext::createContext(WglContext* shared) return; } - currentContext = NULL; + WglContextImpl::currentContext = NULL; } } @@ -728,7 +737,7 @@ void WglContext::createContext(WglContext* shared) static Mutex mutex; Lock lock(mutex); - if (currentContext == shared) + if (WglContextImpl::currentContext == shared) { if (wglMakeCurrent(shared->m_deviceContext, NULL) == FALSE) { @@ -736,7 +745,7 @@ void WglContext::createContext(WglContext* shared) return; } - currentContext = NULL; + WglContextImpl::currentContext = NULL; } if (wglShareLists(sharedContext, m_context) == FALSE) @@ -749,7 +758,7 @@ void WglContext::createContext(WglContext* shared) if (!shared && m_context) { makeCurrent(true); - ensureExtensionsInit(m_deviceContext); + WglContextImpl::ensureExtensionsInit(m_deviceContext); makeCurrent(false); } } diff --git a/src/SFML/Window/Win32/WindowImplWin32.cpp b/src/SFML/Window/Win32/WindowImplWin32.cpp index a424843e2..92e8b8cf2 100755 --- a/src/SFML/Window/Win32/WindowImplWin32.cpp +++ b/src/SFML/Window/Win32/WindowImplWin32.cpp @@ -31,6 +31,9 @@ #ifdef _WIN32_WINNT #undef _WIN32_WINNT #endif +#ifdef WINVER + #undef WINVER +#endif #define _WIN32_WINDOWS 0x0501 #define _WIN32_WINNT 0x0501 #define WINVER 0x0501 diff --git a/src/SFML/Window/WindowBase.cpp b/src/SFML/Window/WindowBase.cpp index e2989a9c7..fc6f780d9 100644 --- a/src/SFML/Window/WindowBase.cpp +++ b/src/SFML/Window/WindowBase.cpp @@ -33,7 +33,11 @@ namespace { - const sf::WindowBase* fullscreenWindow = NULL; + // A nested named namespace is used here to allow unity builds of SFML. + namespace WindowsBaseImpl + { + const sf::WindowBase* fullscreenWindow = NULL; + } } @@ -366,14 +370,14 @@ void WindowBase::initialize() //////////////////////////////////////////////////////////// const WindowBase* WindowBase::getFullscreenWindow() { - return fullscreenWindow; + return WindowsBaseImpl::fullscreenWindow; } //////////////////////////////////////////////////////////// void WindowBase::setFullscreenWindow(const WindowBase* window) { - fullscreenWindow = window; + WindowsBaseImpl::fullscreenWindow = window; } } // namespace sf