summaryrefslogtreecommitdiff
path: root/src/SFML/Window
diff options
context:
space:
mode:
authorJames Cowgill <jcowgill@debian.org>2016-10-27 18:34:24 +0100
committerJames Cowgill <jcowgill@debian.org>2016-10-27 18:34:24 +0100
commitfc50d231530ae85da5cc3f3ebd131310c15bf359 (patch)
tree12c9f3c3f01ee1182d399593347a8611217bbb6c /src/SFML/Window
parentdf93e238e30e97850d76ad5585b8ab9ad9c03e67 (diff)
New upstream version 2.4.1~git15.b61c2f8+dfsg
Diffstat (limited to 'src/SFML/Window')
-rw-r--r--src/SFML/Window/CMakeLists.txt16
-rw-r--r--src/SFML/Window/Context.cpp80
-rw-r--r--src/SFML/Window/EglContext.cpp10
-rw-r--r--src/SFML/Window/EglContext.hpp4
-rw-r--r--src/SFML/Window/GlContext.cpp210
-rw-r--r--src/SFML/Window/GlContext.hpp28
-rw-r--r--src/SFML/Window/GlResource.cpp46
-rw-r--r--src/SFML/Window/OSX/SFContext.hpp4
-rw-r--r--src/SFML/Window/OSX/SFContext.mm29
-rw-r--r--src/SFML/Window/OSX/SFOpenGLView+mouse.mm2
-rw-r--r--src/SFML/Window/OSX/SFOpenGLView+mouse_priv.h3
-rw-r--r--src/SFML/Window/Unix/Display.cpp89
-rw-r--r--src/SFML/Window/Unix/Display.hpp56
-rw-r--r--src/SFML/Window/Unix/GlxContext.cpp81
-rw-r--r--src/SFML/Window/Unix/GlxContext.hpp7
-rw-r--r--src/SFML/Window/Unix/InputImpl.cpp188
-rw-r--r--src/SFML/Window/Unix/ScopedXcbPtr.hpp102
-rw-r--r--src/SFML/Window/Unix/ScopedXcbPtr.inl72
-rw-r--r--src/SFML/Window/Unix/VideoModeImpl.cpp274
-rw-r--r--src/SFML/Window/Unix/WindowImplX11.cpp1512
-rw-r--r--src/SFML/Window/Unix/WindowImplX11.hpp96
-rw-r--r--src/SFML/Window/Win32/WglContext.cpp22
-rw-r--r--src/SFML/Window/Win32/WglContext.hpp4
-rw-r--r--src/SFML/Window/iOS/EaglContext.hpp4
-rw-r--r--src/SFML/Window/iOS/EaglContext.mm21
-rw-r--r--src/SFML/Window/iOS/SFAppDelegate.mm4
26 files changed, 1159 insertions, 1805 deletions
diff --git a/src/SFML/Window/CMakeLists.txt b/src/SFML/Window/CMakeLists.txt
index 231dee8..a887766 100644
--- a/src/SFML/Window/CMakeLists.txt
+++ b/src/SFML/Window/CMakeLists.txt
@@ -75,8 +75,6 @@ elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD)
${SRCROOT}/Unix/Display.hpp
${SRCROOT}/Unix/InputImpl.cpp
${SRCROOT}/Unix/InputImpl.hpp
- ${SRCROOT}/Unix/ScopedXcbPtr.hpp
- ${SRCROOT}/Unix/ScopedXcbPtr.inl
${SRCROOT}/Unix/SensorImpl.cpp
${SRCROOT}/Unix/SensorImpl.hpp
${SRCROOT}/Unix/VideoModeImpl.cpp
@@ -200,18 +198,14 @@ if(SFML_OS_LINUX OR SFML_OS_FREEBSD)
if(NOT X11_FOUND)
message(FATAL_ERROR "X11 library not found")
endif()
+ if(NOT X11_Xrandr_FOUND)
+ message(FATAL_ERROR "Xrandr library not found")
+ endif()
include_directories(${X11_INCLUDE_DIR})
endif()
if(NOT SFML_OPENGL_ES)
find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})
- if(SFML_OS_LINUX OR SFML_OS_FREEBSD)
- find_package(XCB COMPONENTS xlib_xcb image randr REQUIRED)
- if(NOT LIBXCB_FOUND)
- message(FATAL_ERROR "Xcb library not found")
- endif()
- include_directories(${LIBXCB_INCLUDE_DIRS})
- endif()
endif()
if(SFML_OPENGL_ES AND SFML_OS_LINUX)
find_package(EGL REQUIRED)
@@ -231,9 +225,9 @@ endif()
if(SFML_OS_WINDOWS)
list(APPEND WINDOW_EXT_LIBS winmm gdi32)
elseif(SFML_OS_LINUX)
- list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${LIBXCB_LIBRARIES} ${UDEV_LIBRARIES})
+ list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${X11_Xrandr_LIB} ${UDEV_LIBRARIES})
elseif(SFML_OS_FREEBSD)
- list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${LIBXCB_LIBRARIES} usbhid)
+ list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${X11_Xrandr_LIB} usbhid)
elseif(SFML_OS_MACOSX)
list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework AppKit -framework IOKit -framework Carbon")
elseif(SFML_OS_IOS)
diff --git a/src/SFML/Window/Context.cpp b/src/SFML/Window/Context.cpp
index 2d51bbc..7617e1a 100644
--- a/src/SFML/Window/Context.cpp
+++ b/src/SFML/Window/Context.cpp
@@ -28,24 +28,6 @@
#include <SFML/Window/Context.hpp>
#include <SFML/Window/GlContext.hpp>
#include <SFML/System/ThreadLocalPtr.hpp>
-#include <SFML/OpenGL.hpp>
-#include <algorithm>
-#include <vector>
-#include <string>
-
-#if defined(SFML_SYSTEM_WINDOWS)
-
- typedef const GLubyte* (APIENTRY *glGetStringiFuncType)(GLenum, GLuint);
-
-#else
-
- typedef const GLubyte* (*glGetStringiFuncType)(GLenum, GLuint);
-
-#endif
-
-#if !defined(GL_NUM_EXTENSIONS)
- #define GL_NUM_EXTENSIONS 0x821D
-#endif
namespace
@@ -99,70 +81,16 @@ const Context* Context::getActiveContext()
////////////////////////////////////////////////////////////
-GlFunctionPointer Context::getFunction(const char* name)
+bool Context::isExtensionAvailable(const char* name)
{
- return priv::GlContext::getFunction(name);
+ return priv::GlContext::isExtensionAvailable(name);
}
////////////////////////////////////////////////////////////
-bool Context::isExtensionAvailable(const char* name)
+GlFunctionPointer Context::getFunction(const char* name)
{
- static std::vector<std::string> extensions;
- static bool loaded = false;
-
- if (!loaded)
- {
- const Context* context = getActiveContext();
-
- if (!context)
- return false;
-
- const char* extensionString = NULL;
-
- if(context->getSettings().majorVersion < 3)
- {
- // Try to load the < 3.0 way
- extensionString = reinterpret_cast<const char*>(glGetString(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
- glGetStringiFuncType glGetStringiFunc = NULL;
- glGetStringiFunc = reinterpret_cast<glGetStringiFuncType>(getFunction("glGetStringi"));
-
- if (glGetStringiFunc)
- {
- int numExtensions = 0;
- glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
-
- if (numExtensions)
- {
- for (unsigned int i = 0; i < static_cast<unsigned int>(numExtensions); ++i)
- {
- extensionString = reinterpret_cast<const char*>(glGetStringiFunc(GL_EXTENSIONS, i));
-
- extensions.push_back(extensionString);
- }
- }
- }
- }
-
- loaded = true;
- }
-
- return std::find(extensions.begin(), extensions.end(), name) != extensions.end();
+ return priv::GlContext::getFunction(name);
}
diff --git a/src/SFML/Window/EglContext.cpp b/src/SFML/Window/EglContext.cpp
index f6686f1..03c4197 100644
--- a/src/SFML/Window/EglContext.cpp
+++ b/src/SFML/Window/EglContext.cpp
@@ -173,9 +173,12 @@ EglContext::~EglContext()
////////////////////////////////////////////////////////////
-bool EglContext::makeCurrent()
+bool EglContext::makeCurrent(bool current)
{
- return m_surface != EGL_NO_SURFACE && eglCheck(eglMakeCurrent(m_display, m_surface, m_surface, m_context));
+ if (current)
+ return m_surface != EGL_NO_SURFACE && eglCheck(eglMakeCurrent(m_display, m_surface, m_surface, m_context));
+
+ return m_surface != EGL_NO_SURFACE && eglCheck(eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
}
@@ -209,6 +212,9 @@ void EglContext::createContext(EglContext* shared)
else
toShared = EGL_NO_CONTEXT;
+ if (toShared != EGL_NO_CONTEXT)
+ eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
// Create EGL context
m_context = eglCheck(eglCreateContext(m_display, m_config, toShared, contextVersion));
}
diff --git a/src/SFML/Window/EglContext.hpp b/src/SFML/Window/EglContext.hpp
index 6df6a53..a889c3a 100644
--- a/src/SFML/Window/EglContext.hpp
+++ b/src/SFML/Window/EglContext.hpp
@@ -83,10 +83,12 @@ public:
/// \brief Activate the context as the current target
/// for rendering
///
+ /// \param current Whether to make the context current or no longer current
+ ///
/// \return True on success, false if any error happened
///
////////////////////////////////////////////////////////////
- virtual bool makeCurrent();
+ virtual bool makeCurrent(bool current);
////////////////////////////////////////////////////////////
/// \brief Display what has been rendered to the context so far
diff --git a/src/SFML/Window/GlContext.cpp b/src/SFML/Window/GlContext.cpp
index b74725e..23cf483 100644
--- a/src/SFML/Window/GlContext.cpp
+++ b/src/SFML/Window/GlContext.cpp
@@ -31,9 +31,13 @@
#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
#include <SFML/OpenGL.hpp>
+#include <algorithm>
+#include <vector>
+#include <string>
#include <set>
#include <cstdlib>
#include <cstring>
+#include <cassert>
#if !defined(SFML_OPENGL_ES)
@@ -126,6 +130,8 @@ 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
sf::Mutex mutex;
// This per-thread variable holds the current context for each thread
@@ -134,35 +140,12 @@ namespace
// The hidden, inactive context that will be shared with all other contexts
ContextType* sharedContext = NULL;
- // Internal contexts
- sf::ThreadLocalPtr<sf::Context> internalContext(NULL);
- std::set<sf::Context*> internalContexts;
- sf::Mutex internalContextsMutex;
+ // This per-thread variable is set to point to the shared context
+ // if we had to acquire it when a TransientContextLock was required
+ sf::ThreadLocalPtr<sf::priv::GlContext> currentSharedContext(NULL);
- // Check if the internal context of the current thread is valid
- bool hasInternalContext()
- {
- // The internal context can be null...
- if (!internalContext)
- return false;
-
- // ... or non-null but deleted from the list of internal contexts
- sf::Lock lock(internalContextsMutex);
- return internalContexts.find(internalContext) != internalContexts.end();
- }
-
- // Retrieve the internal context for the current thread
- sf::Context* getInternalContext()
- {
- if (!hasInternalContext())
- {
- internalContext = new sf::Context;
- sf::Lock lock(internalContextsMutex);
- internalContexts.insert(internalContext);
- }
-
- return internalContext;
- }
+ // Supported OpenGL extensions
+ std::vector<std::string> extensions;
}
@@ -182,9 +165,53 @@ void GlContext::globalInit()
sharedContext = new ContextType(NULL);
sharedContext->initialize(ContextSettings());
- // This call makes sure that:
- // - the shared context is inactive (it must never be)
- // - another valid context is activated in the current thread
+ // Load our extensions vector
+ extensions.clear();
+
+ // Check whether a >= 3.0 context is available
+ int majorVersion = 0;
+ glGetIntegerv(GL_MAJOR_VERSION, &majorVersion);
+
+ if (glGetError() == GL_INVALID_ENUM)
+ {
+ // Try to load the < 3.0 way
+ const char* extensionString = reinterpret_cast<const char*>(glGetString(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
+ glGetStringiFuncType glGetStringiFunc = NULL;
+ glGetStringiFunc = reinterpret_cast<glGetStringiFuncType>(getFunction("glGetStringi"));
+
+ if (glGetStringiFunc)
+ {
+ int numExtensions = 0;
+ glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
+
+ if (numExtensions)
+ {
+ for (unsigned int i = 0; i < static_cast<unsigned int>(numExtensions); ++i)
+ {
+ const char* extensionString = reinterpret_cast<const char*>(glGetStringiFunc(GL_EXTENSIONS, i));
+
+ extensions.push_back(extensionString);
+ }
+ }
+ }
+ }
+
+ // Deactivate the shared context so that others can activate it when necessary
sharedContext->setActive(false);
}
@@ -200,31 +227,65 @@ void GlContext::globalCleanup()
// Destroy the shared context
delete sharedContext;
sharedContext = NULL;
-
- // Destroy the internal contexts
- Lock internalContextsLock(internalContextsMutex);
- for (std::set<Context*>::iterator it = internalContexts.begin(); it != internalContexts.end(); ++it)
- delete *it;
- internalContexts.clear();
}
////////////////////////////////////////////////////////////
void GlContext::ensureContext()
{
- // If there's no active context on the current thread, activate an internal one
- if (!currentContext)
- getInternalContext()->setActive(true);
+}
+
+
+////////////////////////////////////////////////////////////
+void GlContext::acquireTransientContext()
+{
+ // If a capable context is already active on this thread
+ // there is no need to use the shared context for the operation
+ if (currentContext)
+ {
+ currentSharedContext = NULL;
+ return;
+ }
+
+ mutex.lock();
+ currentSharedContext = sharedContext;
+ sharedContext->setActive(true);
+}
+
+
+////////////////////////////////////////////////////////////
+void GlContext::releaseTransientContext()
+{
+ if (!currentSharedContext)
+ return;
+
+ sharedContext->setActive(false);
+ mutex.unlock();
}
////////////////////////////////////////////////////////////
GlContext* GlContext::create()
{
+ // Make sure that there's an active context (context creation may need extensions, and thus a valid context)
+ assert(sharedContext != NULL);
+
Lock lock(mutex);
- // Create the context
- GlContext* context = new ContextType(sharedContext);
+ GlContext* context = NULL;
+
+ // We don't use acquireTransientContext here since we have
+ // to ensure we have exclusive access to the shared context
+ // in order to make sure it is not active during context creation
+ {
+ sharedContext->setActive(true);
+
+ // Create the context
+ context = new ContextType(sharedContext);
+
+ sharedContext->setActive(false);
+ }
+
context->initialize(ContextSettings());
return context;
@@ -235,12 +296,24 @@ GlContext* GlContext::create()
GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel)
{
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
- ensureContext();
+ assert(sharedContext != NULL);
Lock lock(mutex);
- // Create the context
- GlContext* context = new ContextType(sharedContext, settings, owner, bitsPerPixel);
+ GlContext* context = NULL;
+
+ // We don't use acquireTransientContext here since we have
+ // to ensure we have exclusive access to the shared context
+ // in order to make sure it is not active during context creation
+ {
+ sharedContext->setActive(true);
+
+ // Create the context
+ context = new ContextType(sharedContext, settings, owner, bitsPerPixel);
+
+ sharedContext->setActive(false);
+ }
+
context->initialize(settings);
context->checkSettings(settings);
@@ -252,12 +325,24 @@ GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl*
GlContext* GlContext::create(const ContextSettings& settings, unsigned int width, unsigned int height)
{
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
- ensureContext();
+ assert(sharedContext != NULL);
Lock lock(mutex);
- // Create the context
- GlContext* context = new ContextType(sharedContext, settings, width, height);
+ GlContext* context = NULL;
+
+ // We don't use acquireTransientContext here since we have
+ // to ensure we have exclusive access to the shared context
+ // in order to make sure it is not active during context creation
+ {
+ sharedContext->setActive(true);
+
+ // Create the context
+ context = new ContextType(sharedContext, settings, width, height);
+
+ sharedContext->setActive(false);
+ }
+
context->initialize(settings);
context->checkSettings(settings);
@@ -266,6 +351,13 @@ GlContext* GlContext::create(const ContextSettings& settings, unsigned int width
////////////////////////////////////////////////////////////
+bool GlContext::isExtensionAvailable(const char* name)
+{
+ return std::find(extensions.begin(), extensions.end(), name) != extensions.end();
+}
+
+
+////////////////////////////////////////////////////////////
GlFunctionPointer GlContext::getFunction(const char* name)
{
#if !defined(SFML_OPENGL_ES)
@@ -287,7 +379,10 @@ GlContext::~GlContext()
{
// Deactivate the context before killing it, unless we're inside Cleanup()
if (sharedContext)
- setActive(false);
+ {
+ if (this == currentContext)
+ currentContext = NULL;
+ }
}
@@ -308,7 +403,7 @@ bool GlContext::setActive(bool active)
Lock lock(mutex);
// Activate the context
- if (makeCurrent())
+ if (makeCurrent(true))
{
// Set it as the new current context for this thread
currentContext = this;
@@ -329,9 +424,18 @@ bool GlContext::setActive(bool active)
{
if (this == currentContext)
{
- // To deactivate the context, we actually activate another one so that we make
- // sure that there is always an active context for subsequent graphics operations
- return getInternalContext()->setActive(true);
+ Lock lock(mutex);
+
+ // Deactivate the context
+ if (makeCurrent(false))
+ {
+ currentContext = NULL;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
else
{
diff --git a/src/SFML/Window/GlContext.hpp b/src/SFML/Window/GlContext.hpp
index 8c4ce01..abcda4b 100644
--- a/src/SFML/Window/GlContext.hpp
+++ b/src/SFML/Window/GlContext.hpp
@@ -73,10 +73,22 @@ public:
static void globalCleanup();
////////////////////////////////////////////////////////////
- /// \brief Ensures that an OpenGL context is active in the current thread
+ /// \brief Empty function for ABI compatibility, use acquireTransientContext instead
///
////////////////////////////////////////////////////////////
static void ensureContext();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Acquires a context for short-term use on the current thread
+ ///
+ ////////////////////////////////////////////////////////////
+ static void acquireTransientContext();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Releases a context after short-term use on the current thread
+ ///
+ ////////////////////////////////////////////////////////////
+ static void releaseTransientContext();
////////////////////////////////////////////////////////////
/// \brief Create a new context, not associated to a window
@@ -121,6 +133,16 @@ public:
public:
////////////////////////////////////////////////////////////
+ /// \brief Check whether a given OpenGL extension is available
+ ///
+ /// \param name Name of the extension to check for
+ ///
+ /// \return True if available, false if unavailable
+ ///
+ ////////////////////////////////////////////////////////////
+ static bool isExtensionAvailable(const char* name);
+
+ ////////////////////////////////////////////////////////////
/// \brief Get the address of an OpenGL function
///
/// \param name Name of the function to get the address of
@@ -197,10 +219,12 @@ protected:
/// \brief Activate the context as the current target
/// for rendering
///
+ /// \param current Whether to make the context current or no longer current
+ ///
/// \return True on success, false if any error happened
///
////////////////////////////////////////////////////////////
- virtual bool makeCurrent() = 0;
+ virtual bool makeCurrent(bool current) = 0;
////////////////////////////////////////////////////////////
/// \brief Evaluate a pixel format configuration
diff --git a/src/SFML/Window/GlResource.cpp b/src/SFML/Window/GlResource.cpp
index dfcbe7a..a3cdddf 100644
--- a/src/SFML/Window/GlResource.cpp
+++ b/src/SFML/Window/GlResource.cpp
@@ -27,6 +27,7 @@
////////////////////////////////////////////////////////////
#include <SFML/Window/GlResource.hpp>
#include <SFML/Window/GlContext.hpp>
+#include <SFML/Window/Context.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
@@ -44,20 +45,15 @@ namespace sf
////////////////////////////////////////////////////////////
GlResource::GlResource()
{
- {
- // Protect from concurrent access
- Lock lock(mutex);
-
- // If this is the very first resource, trigger the global context initialization
- if (count == 0)
- priv::GlContext::globalInit();
+ // Protect from concurrent access
+ Lock lock(mutex);
- // Increment the resources counter
- count++;
- }
+ // If this is the very first resource, trigger the global context initialization
+ if (count == 0)
+ priv::GlContext::globalInit();
- // Now make sure that there is an active OpenGL context in the current thread
- priv::GlContext::ensureContext();
+ // Increment the resources counter
+ count++;
}
@@ -77,9 +73,31 @@ GlResource::~GlResource()
////////////////////////////////////////////////////////////
-void GlResource::ensureGlContext()
+GlResource::TransientContextLock::TransientContextLock() :
+m_context(0)
+{
+ Lock lock(mutex);
+
+ if (count == 0)
+ {
+ m_context = new Context;
+ return;
+ }
+
+ priv::GlContext::acquireTransientContext();
+}
+
+
+////////////////////////////////////////////////////////////
+GlResource::TransientContextLock::~TransientContextLock()
{
- priv::GlContext::ensureContext();
+ if (m_context)
+ {
+ delete m_context;
+ return;
+ }
+
+ priv::GlContext::releaseTransientContext();
}
} // namespace sf
diff --git a/src/SFML/Window/OSX/SFContext.hpp b/src/SFML/Window/OSX/SFContext.hpp
index 3e2a979..75e6794 100644
--- a/src/SFML/Window/OSX/SFContext.hpp
+++ b/src/SFML/Window/OSX/SFContext.hpp
@@ -137,10 +137,12 @@ protected:
/// \brief Activate the context as the current target
/// for rendering
///
+ /// \param current Whether to make the context current or no longer current
+ ///
/// \return True on success, false if any error happened
///
////////////////////////////////////////////////////////////
- virtual bool makeCurrent();
+ virtual bool makeCurrent(bool current);
private:
////////////////////////////////////////////////////////////
diff --git a/src/SFML/Window/OSX/SFContext.mm b/src/SFML/Window/OSX/SFContext.mm
index 0970007..d458a6e 100644
--- a/src/SFML/Window/OSX/SFContext.mm
+++ b/src/SFML/Window/OSX/SFContext.mm
@@ -104,6 +104,10 @@ m_window(0)
SFContext::~SFContext()
{
[m_context clearDrawable];
+
+ if (m_context == [NSOpenGLContext currentContext])
+ [NSOpenGLContext clearCurrentContext];
+
[m_context release];
[m_view release]; // Might be nil but we don't care.
@@ -124,10 +128,18 @@ GlFunctionPointer SFContext::getFunction(const char* name)
////////////////////////////////////////////////////////////
-bool SFContext::makeCurrent()
+bool SFContext::makeCurrent(bool current)
{
- [m_context makeCurrentContext];
- return m_context == [NSOpenGLContext currentContext]; // Should be true.
+ if (current)
+ {
+ [m_context makeCurrentContext];
+ return m_context == [NSOpenGLContext currentContext]; // Should be true.
+ }
+ else
+ {
+ [NSOpenGLContext clearCurrentContext];
+ return m_context != [NSOpenGLContext currentContext]; // Should be true.
+ }
}
@@ -257,6 +269,17 @@ void SFContext::createContext(SFContext* shared,
// Use the shared context if one is given.
NSOpenGLContext* sharedContext = shared != NULL ? shared->m_context : nil;
+ if (sharedContext != nil)
+ {
+ [NSOpenGLContext clearCurrentContext];
+
+ if (sharedContext == [NSOpenGLContext currentContext])
+ {
+ sf::err() << "Failed to deactivate shared context before sharing" << std::endl;
+ return;
+ }
+ }
+
// Create the context.
m_context = [[NSOpenGLContext alloc] initWithFormat:pixFmt
shareContext:sharedContext];
diff --git a/src/SFML/Window/OSX/SFOpenGLView+mouse.mm b/src/SFML/Window/OSX/SFOpenGLView+mouse.mm
index 6349081..5cc1f89 100644
--- a/src/SFML/Window/OSX/SFOpenGLView+mouse.mm
+++ b/src/SFML/Window/OSX/SFOpenGLView+mouse.mm
@@ -230,7 +230,7 @@
////////////////////////////////////////////////////////
-(BOOL)isCursorCurrentlyGrabbed
{
- return [[self window] isKeyWindow] && (m_cursorGrabbed || m_fullscreen);
+ return [[self window] isKeyWindow] && m_cursorGrabbed;
}
diff --git a/src/SFML/Window/OSX/SFOpenGLView+mouse_priv.h b/src/SFML/Window/OSX/SFOpenGLView+mouse_priv.h
index f9b2ab7..27cd388 100644
--- a/src/SFML/Window/OSX/SFOpenGLView+mouse_priv.h
+++ b/src/SFML/Window/OSX/SFOpenGLView+mouse_priv.h
@@ -70,8 +70,7 @@
/// \brief Check whether the cursor is grabbed or not
///
/// The cursor is grabbed if the window is active (key) and
-/// either it is in fullscreen mode or the user wants to
-/// grab it.
+/// the user wants to grab it.
///
////////////////////////////////////////////////////////////
-(BOOL)isCursorCurrentlyGrabbed;
diff --git a/src/SFML/Window/Unix/Display.cpp b/src/SFML/Window/Unix/Display.cpp
index a078b97..7445508 100644
--- a/src/SFML/Window/Unix/Display.cpp
+++ b/src/SFML/Window/Unix/Display.cpp
@@ -26,10 +26,12 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Err.hpp>
+#include <SFML/System/Mutex.hpp>
+#include <SFML/System/Lock.hpp>
#include <SFML/Window/Unix/Display.hpp>
-#include <SFML/Window/Unix/ScopedXcbPtr.hpp>
#include <X11/keysym.h>
#include <cassert>
+#include <cstdlib>
#include <map>
@@ -38,8 +40,9 @@ namespace
// The shared display and its reference counter
Display* sharedDisplay = NULL;
unsigned int referenceCount = 0;
+ sf::Mutex mutex;
- typedef std::map<std::string, xcb_atom_t> AtomMap;
+ typedef std::map<std::string, Atom> AtomMap;
AtomMap atoms;
}
@@ -50,6 +53,8 @@ namespace priv
////////////////////////////////////////////////////////////
Display* OpenDisplay()
{
+ Lock lock(mutex);
+
if (referenceCount == 0)
{
sharedDisplay = XOpenDisplay(NULL);
@@ -69,15 +74,10 @@ Display* OpenDisplay()
////////////////////////////////////////////////////////////
-xcb_connection_t* OpenConnection()
-{
- return XGetXCBConnection(OpenDisplay());
-}
-
-
-////////////////////////////////////////////////////////////
void CloseDisplay(Display* display)
{
+ Lock lock(mutex);
+
assert(display == sharedDisplay);
referenceCount--;
@@ -87,81 +87,22 @@ void CloseDisplay(Display* display)
////////////////////////////////////////////////////////////
-void CloseConnection(xcb_connection_t* connection)
-{
- assert(connection == XGetXCBConnection(sharedDisplay));
- return CloseDisplay(sharedDisplay);
-}
-
-
-////////////////////////////////////////////////////////////
-xcb_screen_t* XCBScreenOfDisplay(xcb_connection_t* connection, int screen_nbr)
-{
- xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_get_setup(connection));
-
- for (; iter.rem; --screen_nbr, xcb_screen_next (&iter))
- {
- if (screen_nbr == 0)
- return iter.data;
- }
-
- return NULL;
-}
-
-
-////////////////////////////////////////////////////////////
-xcb_screen_t* XCBDefaultScreen(xcb_connection_t* connection)
-{
- assert(connection == XGetXCBConnection(sharedDisplay));
- return XCBScreenOfDisplay(connection, XDefaultScreen(sharedDisplay));
-}
-
-
-////////////////////////////////////////////////////////////
-xcb_window_t XCBDefaultRootWindow(xcb_connection_t* connection)
-{
- assert(connection == XGetXCBConnection(sharedDisplay));
- xcb_screen_t* screen = XCBScreenOfDisplay(connection, XDefaultScreen(sharedDisplay));
- if (screen)
- return screen->root;
- return 0;
-}
-
-
-////////////////////////////////////////////////////////////
-xcb_atom_t getAtom(const std::string& name, bool onlyIfExists)
+Atom getAtom(const std::string& name, bool onlyIfExists)
{
AtomMap::const_iterator iter = atoms.find(name);
if (iter != atoms.end())
return iter->second;
- ScopedXcbPtr<xcb_generic_error_t> error(NULL);
+ Display* display = OpenDisplay();
- xcb_connection_t* connection = OpenConnection();
+ Atom atom = XInternAtom(display, name.c_str(), onlyIfExists ? True : False);
- ScopedXcbPtr<xcb_intern_atom_reply_t> reply(xcb_intern_atom_reply(
- connection,
- xcb_intern_atom(
- connection,
- onlyIfExists,
- name.size(),
- name.c_str()
- ),
- &error
- ));
-
- CloseConnection(connection);
-
- if (error || !reply)
- {
- err() << "Failed to get " << name << " atom." << std::endl;
- return XCB_ATOM_NONE;
- }
+ CloseDisplay(display);
- atoms[name] = reply->atom;
+ atoms[name] = atom;
- return reply->atom;
+ return atom;
}
} // namespace priv
diff --git a/src/SFML/Window/Unix/Display.hpp b/src/SFML/Window/Unix/Display.hpp
index 2743678..f0eb302 100644
--- a/src/SFML/Window/Unix/Display.hpp
+++ b/src/SFML/Window/Unix/Display.hpp
@@ -28,7 +28,7 @@
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
-#include <X11/Xlib-xcb.h>
+#include <X11/Xlib.h>
#include <string>
@@ -48,17 +48,6 @@ namespace priv
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 CloseConnection.
-///
-/// \return Pointer to the shared connection
-///
-////////////////////////////////////////////////////////////
-xcb_connection_t* OpenConnection();
-
-////////////////////////////////////////////////////////////
/// \brief Release a reference to the shared display
///
/// \param display Display to release
@@ -67,54 +56,15 @@ xcb_connection_t* OpenConnection();
void CloseDisplay(Display* display);
////////////////////////////////////////////////////////////
-/// \brief Release a reference to the shared display
-///
-/// \param connection Connection of display to release
-///
-////////////////////////////////////////////////////////////
-void CloseConnection(xcb_connection_t* connection);
-
-////////////////////////////////////////////////////////////
-/// \brief Get screen of a display by index (equivalent to XScreenOfDisplay)
-///
-/// \param connection Connection of display
-/// \param screen_nbr The index of the screen
-///
-/// \return Pointer to the screen
-///
-////////////////////////////////////////////////////////////
-xcb_screen_t* XCBScreenOfDisplay(xcb_connection_t* connection, int screen_nbr);
-
-////////////////////////////////////////////////////////////
-/// \brief Get default screen of a display (equivalent to XDefaultScreen)
-///
-/// \param connection Connection of display
-///
-/// \return Pointer to the default screen of the display
-///
-////////////////////////////////////////////////////////////
-xcb_screen_t* XCBDefaultScreen(xcb_connection_t* connection);
-
-////////////////////////////////////////////////////////////
-/// \brief Get default root window of a display (equivalent to XDefaultRootWindow)
-///
-/// \param connection Connection of display
-///
-/// \return Root window of the display
-///
-////////////////////////////////////////////////////////////
-xcb_window_t XCBDefaultRootWindow(xcb_connection_t* connection);
-
-////////////////////////////////////////////////////////////
/// \brief Get the atom with the specified name
///
/// \param name Name of the atom
/// \param onlyIfExists Don't try to create the atom if it doesn't already exist
///
-/// \return Atom if it exists or XCB_ATOM_NONE (0) if it doesn't
+/// \return Atom if it exists or None (0) if it doesn't
///
////////////////////////////////////////////////////////////
-xcb_atom_t getAtom(const std::string& name, bool onlyIfExists = false);
+Atom getAtom(const std::string& name, bool onlyIfExists = false);
} // namespace priv
diff --git a/src/SFML/Window/Unix/GlxContext.cpp b/src/SFML/Window/Unix/GlxContext.cpp
index 7251db2..4efee9f 100644
--- a/src/SFML/Window/Unix/GlxContext.cpp
+++ b/src/SFML/Window/Unix/GlxContext.cpp
@@ -194,8 +194,8 @@ GlxContext::~GlxContext()
// Destroy the window if we own it
if (m_window && m_ownsWindow)
{
- xcb_destroy_window(m_connection, m_window);
- xcb_flush(m_connection);
+ XDestroyWindow(m_display, m_window);
+ XFlush(m_display);
}
// Close the connection with the X server
@@ -211,7 +211,7 @@ GlFunctionPointer GlxContext::getFunction(const char* name)
////////////////////////////////////////////////////////////
-bool GlxContext::makeCurrent()
+bool GlxContext::makeCurrent(bool current)
{
if (!m_context)
return false;
@@ -222,13 +222,20 @@ bool GlxContext::makeCurrent()
bool result = false;
- if (m_pbuffer)
+ if (current)
{
- result = glXMakeContextCurrent(m_display, m_pbuffer, m_pbuffer, m_context);
+ if (m_pbuffer)
+ {
+ result = glXMakeContextCurrent(m_display, m_pbuffer, m_pbuffer, m_context);
+ }
+ else if (m_window)
+ {
+ result = glXMakeCurrent(m_display, m_window, m_context);
+ }
}
- else if (m_window)
+ else
{
- result = glXMakeCurrent(m_display, m_window, m_context);
+ result = glXMakeCurrent(m_display, None, NULL);
}
#if defined(GLX_DEBUGGING)
@@ -444,7 +451,6 @@ void GlxContext::updateSettingsFromWindow()
void GlxContext::createSurface(GlxContext* shared, unsigned int width, unsigned int height, unsigned int bitsPerPixel)
{
m_display = OpenDisplay();
- m_connection = XGetXCBConnection(m_display);
// Choose the visual according to the context settings
XVisualInfo visualInfo = selectBestVisual(m_display, bitsPerPixel, m_settings);
@@ -482,8 +488,11 @@ void GlxContext::createSurface(GlxContext* shared, unsigned int width, unsigned
if (visual->visualid == visualInfo.visualid)
{
config = &configs[i];
+ XFree(visual);
break;
}
+
+ XFree(visual);
}
if (config)
@@ -510,28 +519,22 @@ void GlxContext::createSurface(GlxContext* shared, unsigned int width, unsigned
}
// If pbuffers are not available we use a hidden window as the off-screen surface to draw to
- xcb_screen_t* screen = XCBScreenOfDisplay(m_connection, DefaultScreen(m_display));
+ int screen = DefaultScreen(m_display);
// Define the window attributes
- xcb_colormap_t colormap = xcb_generate_id(m_connection);
- xcb_create_colormap(m_connection, XCB_COLORMAP_ALLOC_NONE, colormap, screen->root, visualInfo.visualid);
- const uint32_t value_list[] = {colormap};
-
- // Create a dummy window (disabled and hidden)
- m_window = xcb_generate_id(m_connection);
- xcb_create_window(
- m_connection,
- static_cast<uint8_t>(visualInfo.depth),
- m_window,
- screen->root,
- 0, 0,
- width, height,
- 0,
- XCB_WINDOW_CLASS_INPUT_OUTPUT,
- visualInfo.visualid,
- XCB_CW_COLORMAP,
- value_list
- );
+ XSetWindowAttributes attributes;
+ attributes.colormap = XCreateColormap(m_display, RootWindow(m_display, screen), visualInfo.visual, AllocNone);
+
+ m_window = XCreateWindow(m_display,
+ RootWindow(m_display, screen),
+ 0, 0,
+ width, height,
+ 0,
+ DefaultDepth(m_display, screen),
+ InputOutput,
+ visualInfo.visual,
+ CWColormap,
+ &attributes);
m_ownsWindow = true;
@@ -543,7 +546,6 @@ void GlxContext::createSurface(GlxContext* shared, unsigned int width, unsigned
void GlxContext::createSurface(::Window window)
{
m_display = OpenDisplay();
- m_connection = XGetXCBConnection(m_display);
// A window already exists, so just use it
m_window = window;
@@ -640,8 +642,11 @@ void GlxContext::createContext(GlxContext* shared)
if (visual->visualid == visualInfo->visualid)
{
config = &configs[i];
+ XFree(visual);
break;
}
+
+ XFree(visual);
}
if (!config)
@@ -688,6 +693,15 @@ void GlxContext::createContext(GlxContext* shared)
// On an error, glXCreateContextAttribsARB will return 0 anyway
GlxErrorHandler handler(m_display);
+ if (toShare)
+ {
+ if (!glXMakeCurrent(m_display, None, NULL))
+ {
+ err() << "Failed to deactivate shared context before sharing" << std::endl;
+ return;
+ }
+ }
+
// Create the context
m_context = glXCreateContextAttribsARB(m_display, *config, toShare, true, &attributes[0]);
@@ -734,6 +748,15 @@ void GlxContext::createContext(GlxContext* shared)
GlxErrorHandler handler(m_display);
#endif
+ if (toShare)
+ {
+ if (!glXMakeCurrent(m_display, None, NULL))
+ {
+ err() << "Failed to deactivate shared context before sharing" << std::endl;
+ return;
+ }
+ }
+
// Create the context, using the target window's visual
m_context = glXCreateContext(m_display, visualInfo, toShare, true);
diff --git a/src/SFML/Window/Unix/GlxContext.hpp b/src/SFML/Window/Unix/GlxContext.hpp
index 4a9444f..360906b 100644
--- a/src/SFML/Window/Unix/GlxContext.hpp
+++ b/src/SFML/Window/Unix/GlxContext.hpp
@@ -30,7 +30,7 @@
////////////////////////////////////////////////////////////
#include <SFML/Window/GlContext.hpp>
#include <SFML/Window/Unix/GlxExtensions.hpp>
-#include <X11/Xlib-xcb.h>
+#include <X11/Xlib.h>
namespace sf
@@ -94,10 +94,12 @@ public:
////////////////////////////////////////////////////////////
/// \brief Activate the context as the current target for rendering
///
+ /// \param current Whether to make the context current or no longer current
+ ///
/// \return True on success, false if any error happened
///
////////////////////////////////////////////////////////////
- virtual bool makeCurrent();
+ virtual bool makeCurrent(bool current);
////////////////////////////////////////////////////////////
/// \brief Display what has been rendered to the context so far
@@ -178,7 +180,6 @@ private:
////////////////////////////////////////////////////////////
::Display* m_display; ///< Connection to the X server
::Window m_window; ///< Window to which the context is attached
- xcb_connection_t* m_connection; ///< Pointer to the xcb connection
GLXContext m_context; ///< OpenGL context
GLXPbuffer m_pbuffer; ///< GLX pbuffer ID if one was created
bool m_ownsWindow; ///< Do we own the window associated to the context?
diff --git a/src/SFML/Window/Unix/InputImpl.cpp b/src/SFML/Window/Unix/InputImpl.cpp
index ad62cd5..90cae1a 100644
--- a/src/SFML/Window/Unix/InputImpl.cpp
+++ b/src/SFML/Window/Unix/InputImpl.cpp
@@ -28,9 +28,8 @@
#include <SFML/Window/Window.hpp> // important to be included first (conflict with None)
#include <SFML/Window/Unix/InputImpl.hpp>
#include <SFML/Window/Unix/Display.hpp>
-#include <SFML/Window/Unix/ScopedXcbPtr.hpp>
#include <SFML/System/Err.hpp>
-#include <xcb/xcb.h>
+#include <X11/Xlib.h>
#include <X11/keysym.h>
@@ -157,36 +156,26 @@ bool InputImpl::isKeyPressed(Keyboard::Key key)
Display* display = OpenDisplay();
// Convert to keycode
- xcb_keycode_t keycode = XKeysymToKeycode(display, keysym);
-
- CloseDisplay(display);
-
- ScopedXcbPtr<xcb_generic_error_t> error(NULL);
-
- // Open a connection with the X server
- xcb_connection_t* connection = OpenConnection();
-
- // Get the whole keyboard state
- ScopedXcbPtr<xcb_query_keymap_reply_t> keymap(
- xcb_query_keymap_reply(
- connection,
- xcb_query_keymap(connection),
- &error
- )
- );
+ KeyCode keycode = XKeysymToKeycode(display, keysym);
+ if (keycode != 0)
+ {
+ // Get the whole keyboard state
+ char keys[32];
+ XQueryKeymap(display, keys);
- // Close the connection with the X server
- CloseConnection(connection);
+ // Close the connection with the X server
+ CloseDisplay(display);
- if (error)
+ // Check our keycode
+ return (keys[keycode / 8] & (1 << (keycode % 8))) != 0;
+ }
+ else
{
- err() << "Failed to query keymap" << std::endl;
+ // Close the connection with the X server
+ CloseDisplay(display);
return false;
}
-
- // Check our keycode
- return (keymap->keys[keycode / 8] & (1 << (keycode % 8))) != 0;
}
@@ -201,43 +190,30 @@ void InputImpl::setVirtualKeyboardVisible(bool /*visible*/)
bool InputImpl::isMouseButtonPressed(Mouse::Button button)
{
// Open a connection with the X server
- xcb_connection_t* connection = OpenConnection();
-
- ScopedXcbPtr<xcb_generic_error_t> error(NULL);
-
- // Get pointer mask
- ScopedXcbPtr<xcb_query_pointer_reply_t> pointer(
- xcb_query_pointer_reply(
- connection,
- xcb_query_pointer(
- connection,
- XCBDefaultRootWindow(connection)
- ),
- &error
- )
- );
-
- // Close the connection with the X server
- CloseConnection(connection);
+ Display* display = OpenDisplay();
- if (error)
- {
- err() << "Failed to query pointer" << std::endl;
+ // we don't care about these but they are required
+ ::Window root, child;
+ int wx, wy;
+ int gx, gy;
- return false;
- }
+ unsigned int buttons = 0;
+ XQueryPointer(display, DefaultRootWindow(display), &root, &child, &gx, &gy, &wx, &wy, &buttons);
- uint16_t buttons = pointer->mask;
+ // Close the connection with the X server
+ CloseDisplay(display);
switch (button)
{
- case Mouse::Left: return buttons & XCB_BUTTON_MASK_1;
- case Mouse::Right: return buttons & XCB_BUTTON_MASK_3;
- case Mouse::Middle: return buttons & XCB_BUTTON_MASK_2;
+ case Mouse::Left: return buttons & Button1Mask;
+ case Mouse::Right: return buttons & Button3Mask;
+ case Mouse::Middle: return buttons & Button2Mask;
case Mouse::XButton1: return false; // not supported by X
case Mouse::XButton2: return false; // not supported by X
default: return false;
}
+
+ return false;
}
@@ -245,32 +221,21 @@ bool InputImpl::isMouseButtonPressed(Mouse::Button button)
Vector2i InputImpl::getMousePosition()
{
// Open a connection with the X server
- xcb_connection_t* connection = OpenConnection();
+ Display* display = OpenDisplay();
- ScopedXcbPtr<xcb_generic_error_t> error(NULL);
+ // we don't care about these but they are required
+ ::Window root, child;
+ int x, y;
+ unsigned int buttons;
- ScopedXcbPtr<xcb_query_pointer_reply_t> pointer(
- xcb_query_pointer_reply(
- connection,
- xcb_query_pointer(
- connection,
- XCBDefaultRootWindow(connection)
- ),
- &error
- )
- );
+ int gx = 0;
+ int gy = 0;
+ XQueryPointer(display, DefaultRootWindow(display), &root, &child, &gx, &gy, &x, &y, &buttons);
// Close the connection with the X server
- CloseConnection(connection);
-
- if (error)
- {
- err() << "Failed to query pointer" << std::endl;
-
- return Vector2i(0, 0);
- }
+ CloseDisplay(display);
- return Vector2i(pointer->root_x, pointer->root_y);
+ return Vector2i(gx, gy);
}
@@ -281,32 +246,21 @@ Vector2i InputImpl::getMousePosition(const Window& relativeTo)
if (handle)
{
// Open a connection with the X server
- xcb_connection_t* connection = OpenConnection();
+ Display* display = OpenDisplay();
- ScopedXcbPtr<xcb_generic_error_t> error(NULL);
+ // we don't care about these but they are required
+ ::Window root, child;
+ int gx, gy;
+ unsigned int buttons;
- ScopedXcbPtr<xcb_query_pointer_reply_t> pointer(
- xcb_query_pointer_reply(
- connection,
- xcb_query_pointer(
- connection,
- handle
- ),
- &error
- )
- );
+ int x = 0;
+ int y = 0;
+ XQueryPointer(display, handle, &root, &child, &gx, &gy, &x, &y, &buttons);
// Close the connection with the X server
- CloseConnection(connection);
-
- if (error)
- {
- err() << "Failed to query pointer" << std::endl;
-
- return Vector2i(0, 0);
- }
+ CloseDisplay(display);
- return Vector2i(pointer->win_x, pointer->win_y);
+ return Vector2i(x, y);
}
else
{
@@ -319,27 +273,13 @@ Vector2i InputImpl::getMousePosition(const Window& relativeTo)
void InputImpl::setMousePosition(const Vector2i& position)
{
// Open a connection with the X server
- xcb_connection_t* connection = OpenConnection();
-
- ScopedXcbPtr<xcb_generic_error_t> error(xcb_request_check(
- connection,
- xcb_warp_pointer(
- connection,
- None, // Source window
- XCBDefaultRootWindow(connection), // Destination window
- 0, 0, // Source position
- 0, 0, // Source size
- position.x, position.y // Destination position
- )
- ));
-
- if (error)
- err() << "Failed to set mouse position" << std::endl;
+ Display* display = OpenDisplay();
- xcb_flush(connection);
+ XWarpPointer(display, None, DefaultRootWindow(display), 0, 0, 0, 0, position.x, position.y);
+ XFlush(display);
// Close the connection with the X server
- CloseConnection(connection);
+ CloseDisplay(display);
}
@@ -347,31 +287,17 @@ void InputImpl::setMousePosition(const Vector2i& position)
void InputImpl::setMousePosition(const Vector2i& position, const Window& relativeTo)
{
// Open a connection with the X server
- xcb_connection_t* connection = OpenConnection();
+ Display* display = OpenDisplay();
WindowHandle handle = relativeTo.getSystemHandle();
if (handle)
{
- ScopedXcbPtr<xcb_generic_error_t> error(xcb_request_check(
- connection,
- xcb_warp_pointer(
- connection,
- None, // Source window
- handle, // Destination window
- 0, 0, // Source position
- 0, 0, // Source size
- position.x, position.y // Destination position
- )
- ));
-
- if (error)
- err() << "Failed to set mouse position" << std::endl;
-
- xcb_flush(connection);
+ XWarpPointer(display, None, handle, 0, 0, 0, 0, position.x, position.y);
+ XFlush(display);
}
// Close the connection with the X server
- CloseConnection(connection);
+ CloseDisplay(display);
}
diff --git a/src/SFML/Window/Unix/ScopedXcbPtr.hpp b/src/SFML/Window/Unix/ScopedXcbPtr.hpp
deleted file mode 100644
index f610d81..0000000
--- a/src/SFML/Window/Unix/ScopedXcbPtr.hpp
+++ /dev/null
@@ -1,102 +0,0 @@
-////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2016 Laurent Gomila (laurent@sfml-dev.org)
-//
-// This software is provided 'as-is', without any express or implied warranty.
-// In no event will the authors be held liable for any damages arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it freely,
-// subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented;
-// you must not claim that you wrote the original software.
-// If you use this software in a product, an acknowledgment
-// in the product documentation would be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such,
-// and must not be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source distribution.
-//
-////////////////////////////////////////////////////////////
-
-#ifndef SFML_SCOPEDXCBPTR_HPP
-#define SFML_SCOPEDXCBPTR_HPP
-
-////////////////////////////////////////////////////////////
-// Headers
-////////////////////////////////////////////////////////////
-#include <cstdlib>
-
-
-namespace sf
-{
-namespace priv
-{
-////////////////////////////////////////////////////////////
-/// \brief Scoped pointer that frees memory returned in XCB replies
-///
-////////////////////////////////////////////////////////////
-template<typename T>
-class ScopedXcbPtr
-{
-public:
- ////////////////////////////////////////////////////////////
- /// \brief Constructor
- ///
- /// \param pointer Pointer value to store
- ///
- ////////////////////////////////////////////////////////////
- ScopedXcbPtr(T* pointer);
-
- ////////////////////////////////////////////////////////////
- /// \brief Destructor, calls std::free() on the stored pointer
- ///
- ////////////////////////////////////////////////////////////
- ~ScopedXcbPtr();
-
- ////////////////////////////////////////////////////////////
- /// \brief Structure dereference operator
- ///
- /// \return Stored pointer
- ///
- ////////////////////////////////////////////////////////////
- T* operator ->() const;
-
- ////////////////////////////////////////////////////////////
- /// \brief Address operator.
- ///
- /// \return Address of the stored pointer
- ///
- ////////////////////////////////////////////////////////////
- T** operator &();
-
- ////////////////////////////////////////////////////////////
- /// \brief Check if stored pointer is valid
- ///
- /// \return true if stored pointer is valid
- ///
- ////////////////////////////////////////////////////////////
- operator bool() const;
-
- ////////////////////////////////////////////////////////////
- /// \brief Retrieve the stored pointer.
- ///
- /// \return The stored pointer
- ///
- ////////////////////////////////////////////////////////////
- T* get() const;
-
-private:
- T* m_pointer; ///< Stored pointer
-};
-
-#include <SFML/Window/Unix/ScopedXcbPtr.inl>
-
-} // namespace priv
-
-} // namespace sf
-
-#endif // SFML_SCOPEDXCBPTR_HPP
diff --git a/src/SFML/Window/Unix/ScopedXcbPtr.inl b/src/SFML/Window/Unix/ScopedXcbPtr.inl
deleted file mode 100644
index 5869d91..0000000
--- a/src/SFML/Window/Unix/ScopedXcbPtr.inl
+++ /dev/null
@@ -1,72 +0,0 @@
-////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2016 Laurent Gomila (laurent@sfml-dev.org)
-//
-// This software is provided 'as-is', without any express or implied warranty.
-// In no event will the authors be held liable for any damages arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it freely,
-// subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented;
-// you must not claim that you wrote the original software.
-// If you use this software in a product, an acknowledgment
-// in the product documentation would be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such,
-// and must not be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source distribution.
-//
-////////////////////////////////////////////////////////////
-
-
-////////////////////////////////////////////////////////////
-template <typename T>
-inline ScopedXcbPtr<T>::ScopedXcbPtr(T* pointer) :
-m_pointer(pointer)
-{
-
-}
-
-
-////////////////////////////////////////////////////////////
-template <typename T>
-inline ScopedXcbPtr<T>::~ScopedXcbPtr()
-{
- std::free(m_pointer);
-}
-
-
-////////////////////////////////////////////////////////////
-template <typename T>
-inline T* ScopedXcbPtr<T>::operator ->() const
-{
- return m_pointer;
-}
-
-
-////////////////////////////////////////////////////////////
-template <typename T>
-inline T** ScopedXcbPtr<T>::operator &()
-{
- return &m_pointer;
-}
-
-
-////////////////////////////////////////////////////////////
-template <typename T>
-inline ScopedXcbPtr<T>::operator bool() const
-{
- return m_pointer != NULL;
-}
-
-
-////////////////////////////////////////////////////////////
-template <typename T>
-inline T* ScopedXcbPtr<T>::get() const
-{
- return m_pointer;
-}
diff --git a/src/SFML/Window/Unix/VideoModeImpl.cpp b/src/SFML/Window/Unix/VideoModeImpl.cpp
index f95d323..cd78c54 100644
--- a/src/SFML/Window/Unix/VideoModeImpl.cpp
+++ b/src/SFML/Window/Unix/VideoModeImpl.cpp
@@ -27,9 +27,9 @@
////////////////////////////////////////////////////////////
#include <SFML/Window/VideoModeImpl.hpp>
#include <SFML/Window/Unix/Display.hpp>
-#include <SFML/Window/Unix/ScopedXcbPtr.hpp>
#include <SFML/System/Err.hpp>
-#include <xcb/randr.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrandr.h>
#include <algorithm>
@@ -43,95 +43,78 @@ std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
std::vector<VideoMode> modes;
// Open a connection with the X server
- xcb_connection_t* connection = OpenConnection();
-
- // Retrieve the default screen
- xcb_screen_t* screen = XCBDefaultScreen(connection);
-
- ScopedXcbPtr<xcb_generic_error_t> error(NULL);
-
- const xcb_query_extension_reply_t* randrExt = xcb_get_extension_data(connection, &xcb_randr_id);
-
- if (!randrExt || !randrExt->present)
- {
- // Randr extension is not supported: we cannot get the video modes
- err() << "Failed to use the RandR extension while trying to get the supported video modes" << std::endl;
-
- // Close the connection with the X server
- CloseConnection(connection);
-
- return modes;
- }
-
- // Load RandR and check its version
- ScopedXcbPtr<xcb_randr_query_version_reply_t> randrVersion(xcb_randr_query_version_reply(
- connection,
- xcb_randr_query_version(
- connection,
- 1,
- 1
- ),
- &error
- ));
-
- if (error)
- {
- err() << "Failed to load the RandR extension while trying to get the supported video modes" << std::endl;
-
- // Close the connection with the X server
- CloseConnection(connection);
-
- return modes;
- }
-
- // Get the current configuration
- ScopedXcbPtr<xcb_randr_get_screen_info_reply_t> config(xcb_randr_get_screen_info_reply(
- connection,
- xcb_randr_get_screen_info(
- connection,
- screen->root
- ),
- &error
- ));
-
- if (error)
+ Display* display = OpenDisplay();
+ if (display)
{
- // Failed to get the screen configuration
- err() << "Failed to retrieve the screen configuration while trying to get the supported video modes" << std::endl;
+ // Retrieve the default screen number
+ int screen = DefaultScreen(display);
- // Close the connection with the X server
- CloseConnection(connection);
-
- return modes;
- }
-
- // Get the available screen sizes
- xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config.get());
- if (sizes && (config->nSizes > 0))
- {
- // Get the list of supported depths
- xcb_depth_iterator_t iter = xcb_screen_allowed_depths_iterator(screen);
- // Combine depths and sizes to fill the array of supported modes
- for (; iter.rem; xcb_depth_next(&iter))
+ // Check if the XRandR extension is present
+ int version;
+ if (XQueryExtension(display, "RANDR", &version, &version, &version))
{
- for (int j = 0; j < config->nSizes; ++j)
+ // Get the current configuration
+ XRRScreenConfiguration* config = XRRGetScreenInfo(display, RootWindow(display, screen));
+ if (config)
{
- // Convert to VideoMode
- VideoMode mode(sizes[j].width, sizes[j].height, iter.data->depth);
-
- if (config->rotation == XCB_RANDR_ROTATION_ROTATE_90 ||
- config->rotation == XCB_RANDR_ROTATION_ROTATE_270)
- std::swap(mode.width, mode.height);
-
- // Add it only if it is not already in the array
- if (std::find(modes.begin(), modes.end(), mode) == modes.end())
- modes.push_back(mode);
+ // Get the available screen sizes
+ int nbSizes;
+ XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes);
+ if (sizes && (nbSizes > 0))
+ {
+ // Get the list of supported depths
+ int nbDepths = 0;
+ int* depths = XListDepths(display, screen, &nbDepths);
+ if (depths && (nbDepths > 0))
+ {
+ // Combine depths and sizes to fill the array of supported modes
+ for (int i = 0; i < nbDepths; ++i)
+ {
+ for (int j = 0; j < nbSizes; ++j)
+ {
+ // Convert to VideoMode
+ VideoMode mode(sizes[j].width, sizes[j].height, depths[i]);
+
+ Rotation currentRotation;
+ XRRConfigRotations(config, &currentRotation);
+
+ if (currentRotation == RR_Rotate_90 || currentRotation == RR_Rotate_270)
+ std::swap(mode.width, mode.height);
+
+ // Add it only if it is not already in the array
+ if (std::find(modes.begin(), modes.end(), mode) == modes.end())
+ modes.push_back(mode);
+ }
+ }
+
+ // Free the array of depths
+ XFree(depths);
+ }
+ }
+
+ // Free the configuration instance
+ XRRFreeScreenConfigInfo(config);
+ }
+ else
+ {
+ // Failed to get the screen configuration
+ err() << "Failed to retrieve the screen configuration while trying to get the supported video modes" << std::endl;
}
}
- }
+ else
+ {
+ // XRandr extension is not supported: we cannot get the video modes
+ err() << "Failed to use the XRandR extension while trying to get the supported video modes" << std::endl;
+ }
- // Close the connection with the X server
- CloseConnection(connection);
+ // Close the connection with the X server
+ CloseDisplay(display);
+ }
+ else
+ {
+ // We couldn't connect to the X server
+ err() << "Failed to connect to the X server while trying to get the supported video modes" << std::endl;
+ }
return modes;
}
@@ -143,91 +126,62 @@ VideoMode VideoModeImpl::getDesktopMode()
VideoMode desktopMode;
// Open a connection with the X server
- xcb_connection_t* connection = OpenConnection();
-
- // Retrieve the default screen
- xcb_screen_t* screen = XCBDefaultScreen(connection);
-
- ScopedXcbPtr<xcb_generic_error_t> error(NULL);
-
- // Check if the RandR extension is present
- const xcb_query_extension_reply_t* randrExt = xcb_get_extension_data(connection, &xcb_randr_id);
-
- if (!randrExt || !randrExt->present)
- {
- // Randr extension is not supported: we cannot get the video modes
- err() << "Failed to use the RandR extension while trying to get the desktop video mode" << std::endl;
-
- // Close the connection with the X server
- CloseConnection(connection);
-
- return desktopMode;
- }
-
- // Load RandR and check its version
- ScopedXcbPtr<xcb_randr_query_version_reply_t> randrVersion(xcb_randr_query_version_reply(
- connection,
- xcb_randr_query_version(
- connection,
- 1,
- 1
- ),
- &error
- ));
-
- if (error)
+ Display* display = OpenDisplay();
+ if (display)
{
- err() << "Failed to load the RandR extension while trying to get the desktop video mode" << std::endl;
-
- // Close the connection with the X server
- CloseConnection(connection);
-
- return desktopMode;
- }
+ // Retrieve the default screen number
+ int screen = DefaultScreen(display);
- // Get the current configuration
- ScopedXcbPtr<xcb_randr_get_screen_info_reply_t> config(xcb_randr_get_screen_info_reply(
- connection,
- xcb_randr_get_screen_info(
- connection,
- screen->root
- ),
- &error
- ));
-
- if (error)
- {
- // Failed to get the screen configuration
- err() << "Failed to retrieve the screen configuration while trying to get the desktop video mode" << std::endl;
+ // Check if the XRandR extension is present
+ int version;
+ if (XQueryExtension(display, "RANDR", &version, &version, &version))
+ {
+ // Get the current configuration
+ XRRScreenConfiguration* config = XRRGetScreenInfo(display, RootWindow(display, screen));
+ if (config)
+ {
+ // Get the current video mode
+ Rotation currentRotation;
+ int currentMode = XRRConfigCurrentConfiguration(config, &currentRotation);
+
+ // Get the available screen sizes
+ int nbSizes;
+ XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes);
+ if (sizes && (nbSizes > 0))
+ {
+ desktopMode = VideoMode(sizes[currentMode].width, sizes[currentMode].height, DefaultDepth(display, screen));
+
+ Rotation currentRotation;
+ XRRConfigRotations(config, &currentRotation);
+
+ if (currentRotation == RR_Rotate_90 || currentRotation == RR_Rotate_270)
+ std::swap(desktopMode.width, desktopMode.height);
+ }
+
+ // Free the configuration instance
+ XRRFreeScreenConfigInfo(config);
+ }
+ else
+ {
+ // Failed to get the screen configuration
+ err() << "Failed to retrieve the screen configuration while trying to get the desktop video modes" << std::endl;
+ }
+ }
+ else
+ {
+ // XRandr extension is not supported: we cannot get the video modes
+ err() << "Failed to use the XRandR extension while trying to get the desktop video modes" << std::endl;
+ }
// Close the connection with the X server
- CloseConnection(connection);
-
- return desktopMode;
- }
-
- // Get the current video mode
- xcb_randr_mode_t currentMode = config->sizeID;
-
- // Get the available screen sizes
- int nbSizes = xcb_randr_get_screen_info_sizes_length(config.get());
- xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config.get());
- if (sizes && (nbSizes > 0))
- {
- desktopMode = VideoMode(sizes[currentMode].width, sizes[currentMode].height, screen->root_depth);
-
- if (config->rotation == XCB_RANDR_ROTATION_ROTATE_90 ||
- config->rotation == XCB_RANDR_ROTATION_ROTATE_270)
- std::swap(desktopMode.width, desktopMode.height);
+ CloseDisplay(display);
}
else
{
- err() << "Failed to retrieve any screen sizes while trying to get the desktop video mode" << std::endl;
+ // We couldn't connect to the X server
+ err() << "Failed to connect to the X server while trying to get the desktop video modes" << std::endl;
}
- // Close the connection with the X server
- CloseConnection(connection);
-
return desktopMode;
}
diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp
index 88176bf..530bea5 100644
--- a/src/SFML/Window/Unix/WindowImplX11.cpp
+++ b/src/SFML/Window/Unix/WindowImplX11.cpp
@@ -29,15 +29,16 @@
#include <SFML/Window/Unix/WindowImplX11.hpp>
#include <SFML/Window/Unix/Display.hpp>
#include <SFML/Window/Unix/InputImpl.hpp>
-#include <SFML/Window/Unix/ScopedXcbPtr.hpp>
#include <SFML/System/Utf.hpp>
#include <SFML/System/Err.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Sleep.hpp>
-#include <xcb/xcb_image.h>
-#include <xcb/randr.h>
#include <X11/Xlibint.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include <X11/extensions/Xrandr.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -66,12 +67,12 @@ namespace
sf::Mutex allWindowsMutex;
sf::String windowManagerName;
- static const unsigned long eventMask = XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_BUTTON_PRESS |
- XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_MOTION |
- XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_KEY_PRESS |
- XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_STRUCTURE_NOTIFY |
- XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW |
- XCB_EVENT_MASK_VISIBILITY_CHANGE;
+ static const unsigned long eventMask = FocusChangeMask | ButtonPressMask |
+ ButtonReleaseMask | ButtonMotionMask |
+ PointerMotionMask | KeyPressMask |
+ KeyReleaseMask | StructureNotifyMask |
+ EnterWindowMask | LeaveWindowMask |
+ VisibilityChangeMask | PropertyChangeMask;
static const unsigned int maxTrialsCount = 5;
@@ -127,76 +128,88 @@ namespace
checked = true;
- xcb_connection_t* connection = sf::priv::OpenConnection();
-
- xcb_atom_t netSupportingWmCheck = sf::priv::getAtom("_NET_SUPPORTING_WM_CHECK", true);
- xcb_atom_t netSupported = sf::priv::getAtom("_NET_SUPPORTED", true);
+ Atom netSupportingWmCheck = sf::priv::getAtom("_NET_SUPPORTING_WM_CHECK", true);
+ Atom netSupported = sf::priv::getAtom("_NET_SUPPORTED", true);
if (!netSupportingWmCheck || !netSupported)
return false;
- sf::priv::ScopedXcbPtr<xcb_generic_error_t> error(NULL);
-
- sf::priv::ScopedXcbPtr<xcb_get_property_reply_t> rootSupportingWindow(xcb_get_property_reply(
- connection,
- xcb_get_property(
- connection,
- 0,
- sf::priv::XCBDefaultRootWindow(connection),
- netSupportingWmCheck,
- XCB_ATOM_WINDOW,
- 0,
- 1
- ),
- &error
- ));
-
- if (!rootSupportingWindow || rootSupportingWindow->length != 1)
+ ::Display* display = sf::priv::OpenDisplay();
+
+ Atom actualType;
+ int actualFormat;
+ unsigned long numItems;
+ unsigned long numBytes;
+ unsigned char* data;
+
+ int result = XGetWindowProperty(display,
+ DefaultRootWindow(display),
+ netSupportingWmCheck,
+ 0,
+ 1,
+ False,
+ XA_WINDOW,
+ &actualType,
+ &actualFormat,
+ &numItems,
+ &numBytes,
+ &data);
+
+ if (result != Success || actualType != XA_WINDOW || numItems != 1)
{
- sf::priv::CloseConnection(connection);
+ if(result == Success)
+ XFree(data);
+
+ sf::priv::CloseDisplay(display);
return false;
}
- xcb_window_t* rootWindow = reinterpret_cast<xcb_window_t*>(xcb_get_property_value(rootSupportingWindow.get()));
+ ::Window rootWindow = *reinterpret_cast< ::Window* >(data);
+
+ XFree(data);
if (!rootWindow)
{
- sf::priv::CloseConnection(connection);
+ sf::priv::CloseDisplay(display);
return false;
}
- sf::priv::ScopedXcbPtr<xcb_get_property_reply_t> childSupportingWindow(xcb_get_property_reply(
- connection,
- xcb_get_property(
- connection,
- 0,
- *rootWindow,
- netSupportingWmCheck,
- XCB_ATOM_WINDOW,
- 0,
- 1
- ),
- &error
- ));
-
- if (!childSupportingWindow || childSupportingWindow->length != 1)
+ result = XGetWindowProperty(display,
+ rootWindow,
+ netSupportingWmCheck,
+ 0,
+ 1,
+ False,
+ XA_WINDOW,
+ &actualType,
+ &actualFormat,
+ &numItems,
+ &numBytes,
+ &data);
+
+ if (result != Success || actualType != XA_WINDOW || numItems != 1)
{
- sf::priv::CloseConnection(connection);
+ if(result == Success)
+ XFree(data);
+
+ sf::priv::CloseDisplay(display);
return false;
}
- xcb_window_t* childWindow = reinterpret_cast<xcb_window_t*>(xcb_get_property_value(childSupportingWindow.get()));
+ ::Window childWindow = *reinterpret_cast< ::Window* >(data);
+
+ XFree(data);
if (!childWindow)
{
- sf::priv::CloseConnection(connection);
+ sf::priv::CloseDisplay(display);
return false;
}
// Conforming window managers should return the same window for both queries
- if (*rootWindow != *childWindow)
+ if (rootWindow != childWindow)
{
- sf::priv::CloseConnection(connection);
+ sf::priv::CloseDisplay(display);
return false;
}
@@ -204,45 +217,51 @@ namespace
// We try to get the name of the window manager
// for window manager specific workarounds
- xcb_atom_t netWmName = sf::priv::getAtom("_NET_WM_NAME", true);
- xcb_atom_t utf8StringType = sf::priv::getAtom("UTF8_STRING");
-
- if (!utf8StringType)
- utf8StringType = XCB_ATOM_STRING;
+ Atom netWmName = sf::priv::getAtom("_NET_WM_NAME", true);
if (!netWmName)
{
- sf::priv::CloseConnection(connection);
+ sf::priv::CloseDisplay(display);
return true;
}
- sf::priv::ScopedXcbPtr<xcb_get_property_reply_t> wmName(xcb_get_property_reply(
- connection,
- xcb_get_property(
- connection,
- 0,
- *childWindow,
- netWmName,
- utf8StringType,
- 0,
- 0x7fffffff
- ),
- &error
- ));
-
- sf::priv::CloseConnection(connection);
-
- // 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<const char*>(xcb_get_property_value(wmName.get()));
- const char* end = begin + xcb_get_property_value_length(wmName.get());
- windowManagerName = sf::String::fromUtf8(begin, end);
+ 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<const char*>(data);
+ const char* end = begin + numItems;
+ windowManagerName = sf::String::fromUtf8(begin, end);
+ }
+
+ if(result == Success)
+ XFree(data);
+
+ sf::priv::CloseDisplay(display);
return true;
}
- sf::Keyboard::Key keysymToSF(xcb_keysym_t symbol)
+ sf::Keyboard::Key keysymToSF(KeySym symbol)
{
switch (symbol)
{
@@ -362,34 +381,29 @@ namespace priv
////////////////////////////////////////////////////////////
WindowImplX11::WindowImplX11(WindowHandle handle) :
m_window (0),
-m_screen (NULL),
+m_screen (0),
m_inputMethod (NULL),
m_inputContext (NULL),
m_isExternal (true),
+m_oldVideoMode (0),
m_hiddenCursor (0),
m_keyRepeat (true),
m_previousSize (-1, -1),
m_useSizeHints (false),
m_fullscreen (false),
m_cursorGrabbed (false),
-m_windowMapped (false)
+m_windowMapped (false),
+m_iconPixmap (0),
+m_iconMaskPixmap (0),
+m_lastInputTime (0)
{
// Open a connection with the X server
m_display = OpenDisplay();
- m_connection = XGetXCBConnection(m_display);
-
- std::memset(&m_oldVideoMode, 0, sizeof(m_oldVideoMode));
-
- if (!m_connection)
- {
- err() << "Failed cast Display object to an XCB connection object" << std::endl;
- return;
- }
// Make sure to check for EWMH support before we do anything
ewmhSupported();
- m_screen = XCBDefaultScreen(m_connection);
+ m_screen = DefaultScreen(m_display);
// Save the window handle
m_window = handle;
@@ -397,14 +411,10 @@ m_windowMapped (false)
if (m_window)
{
// Make sure the window is listening to all the required events
- const uint32_t value_list[] = {static_cast<uint32_t>(eventMask)};
+ XSetWindowAttributes attributes;
+ attributes.event_mask = eventMask;
- xcb_change_window_attributes(
- m_connection,
- m_window,
- XCB_CW_EVENT_MASK,
- value_list
- );
+ XChangeWindowAttributes(m_display, m_window, CWEventMask, &attributes);
// Set the WM protocols
setProtocols();
@@ -418,38 +428,33 @@ m_windowMapped (false)
////////////////////////////////////////////////////////////
WindowImplX11::WindowImplX11(VideoMode mode, const String& title, unsigned long style, const ContextSettings& settings) :
m_window (0),
-m_screen (NULL),
+m_screen (0),
m_inputMethod (NULL),
m_inputContext (NULL),
m_isExternal (false),
+m_oldVideoMode (0),
m_hiddenCursor (0),
m_keyRepeat (true),
m_previousSize (-1, -1),
m_useSizeHints (false),
m_fullscreen ((style & Style::Fullscreen) != 0),
m_cursorGrabbed (m_fullscreen),
-m_windowMapped (false)
+m_windowMapped (false),
+m_iconPixmap (0),
+m_iconMaskPixmap (0),
+m_lastInputTime (0)
{
// Open a connection with the X server
m_display = OpenDisplay();
- m_connection = XGetXCBConnection(m_display);
-
- std::memset(&m_oldVideoMode, 0, sizeof(m_oldVideoMode));
-
- if (!m_connection)
- {
- err() << "Failed cast Display object to an XCB connection object" << std::endl;
- return;
- }
// Make sure to check for EWMH support before we do anything
ewmhSupported();
- m_screen = XCBDefaultScreen(m_connection);
+ m_screen = DefaultScreen(m_display);
// Compute position and size
- int left = m_fullscreen ? 0 : (m_screen->width_in_pixels - mode.width) / 2;
- int top = m_fullscreen ? 0 : (m_screen->height_in_pixels - mode.height) / 2;
+ int left = m_fullscreen ? 0 : (DisplayWidth(m_display, m_screen) - mode.width) / 2;
+ int top = m_fullscreen ? 0 : (DisplayHeight(m_display, m_screen) - mode.height) / 2;
int width = mode.width;
int height = mode.height;
@@ -457,31 +462,23 @@ m_windowMapped (false)
XVisualInfo visualInfo = ContextType::selectBestVisual(m_display, mode.bitsPerPixel, settings);
// Define the window attributes
- xcb_colormap_t colormap = xcb_generate_id(m_connection);
- xcb_create_colormap(m_connection, XCB_COLORMAP_ALLOC_NONE, colormap, m_screen->root, visualInfo.visualid);
- const uint32_t value_list[] = {m_fullscreen && !ewmhSupported(), static_cast<uint32_t>(eventMask), colormap};
-
- // Create the window
- m_window = xcb_generate_id(m_connection);
-
- ScopedXcbPtr<xcb_generic_error_t> errptr(xcb_request_check(
- m_connection,
- xcb_create_window_checked(
- m_connection,
- static_cast<uint8_t>(visualInfo.depth),
- m_window,
- m_screen->root,
- left, top,
- width, height,
- 0,
- XCB_WINDOW_CLASS_INPUT_OUTPUT,
- visualInfo.visualid,
- XCB_CW_EVENT_MASK | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_COLORMAP,
- value_list
- )
- ));
-
- if (errptr)
+ XSetWindowAttributes attributes;
+ attributes.colormap = XCreateColormap(m_display, DefaultRootWindow(m_display), visualInfo.visual, AllocNone);
+ attributes.event_mask = eventMask;
+ attributes.override_redirect = (m_fullscreen && !ewmhSupported()) ? True : False;
+
+ m_window = XCreateWindow(m_display,
+ DefaultRootWindow(m_display),
+ left, top,
+ width, height,
+ 0,
+ visualInfo.depth,
+ InputOutput,
+ visualInfo.visual,
+ CWEventMask | CWOverrideRedirect | CWColormap,
+ &attributes);
+
+ if (!m_window)
{
err() << "Failed to create window" << std::endl;
return;
@@ -491,54 +488,113 @@ m_windowMapped (false)
setProtocols();
// Set the WM initial state to the normal state
- WMHints hints;
- std::memset(&hints, 0, sizeof(hints));
- hints.initial_state = 1;
- hints.flags |= 1 << 1;
- setWMHints(hints);
+ XWMHints* hints = XAllocWMHints();
+ hints->flags = StateHint;
+ hints->initial_state = NormalState;
+ XSetWMHints(m_display, m_window, hints);
+ XFree(hints);
// If not in fullscreen, set the window's style (tell the window manager to
// change our window's decorations and functions according to the requested style)
if (!m_fullscreen)
- setMotifHints(style);
+ {
+ Atom WMHintsAtom = getAtom("_MOTIF_WM_HINTS", false);
+ if (WMHintsAtom)
+ {
+ static const unsigned long MWM_HINTS_FUNCTIONS = 1 << 0;
+ static const unsigned long MWM_HINTS_DECORATIONS = 1 << 1;
+
+ //static const unsigned long MWM_DECOR_ALL = 1 << 0;
+ static const unsigned long MWM_DECOR_BORDER = 1 << 1;
+ static const unsigned long MWM_DECOR_RESIZEH = 1 << 2;
+ static const unsigned long MWM_DECOR_TITLE = 1 << 3;
+ static const unsigned long MWM_DECOR_MENU = 1 << 4;
+ static const unsigned long MWM_DECOR_MINIMIZE = 1 << 5;
+ static const unsigned long MWM_DECOR_MAXIMIZE = 1 << 6;
+
+ //static const unsigned long MWM_FUNC_ALL = 1 << 0;
+ static const unsigned long MWM_FUNC_RESIZE = 1 << 1;
+ static const unsigned long MWM_FUNC_MOVE = 1 << 2;
+ static const unsigned long MWM_FUNC_MINIMIZE = 1 << 3;
+ static const unsigned long MWM_FUNC_MAXIMIZE = 1 << 4;
+ static const unsigned long MWM_FUNC_CLOSE = 1 << 5;
+
+ struct WMHints
+ {
+ unsigned long flags;
+ unsigned long functions;
+ unsigned long decorations;
+ long inputMode;
+ unsigned long state;
+ };
+
+ WMHints hints;
+ std::memset(&hints, 0, sizeof(hints));
+ hints.flags = MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS;
+ hints.decorations = 0;
+ hints.functions = 0;
+
+ if (style & Style::Titlebar)
+ {
+ hints.decorations |= MWM_DECOR_BORDER | MWM_DECOR_TITLE | MWM_DECOR_MINIMIZE | MWM_DECOR_MENU;
+ hints.functions |= MWM_FUNC_MOVE | MWM_FUNC_MINIMIZE;
+ }
+ if (style & Style::Resize)
+ {
+ hints.decorations |= MWM_DECOR_MAXIMIZE | MWM_DECOR_RESIZEH;
+ hints.functions |= MWM_FUNC_MAXIMIZE | MWM_FUNC_RESIZE;
+ }
+ if (style & Style::Close)
+ {
+ hints.decorations |= 0;
+ hints.functions |= MWM_FUNC_CLOSE;
+ }
- WMSizeHints sizeHints;
- std::memset(&sizeHints, 0, sizeof(sizeHints));
+ XChangeProperty(m_display,
+ m_window,
+ WMHintsAtom,
+ WMHintsAtom,
+ 32,
+ PropModeReplace,
+ reinterpret_cast<const unsigned char*>(&hints),
+ 5);
+ }
+ }
// This is a hack to force some windows managers to disable resizing
- // Fullscreen is bugged on Openbox. Unless size hints are set, there
- // will be a region of the window that is off-screen. We try to workaround
- // this by setting size hints even in fullscreen just for Openbox.
- if ((!m_fullscreen || (windowManagerName == "Openbox")) && !(style & Style::Resize))
+ if (!(style & Style::Resize))
{
m_useSizeHints = true;
- sizeHints.flags |= ((1 << 4) | (1 << 5));
- sizeHints.min_width = width;
- sizeHints.max_width = width;
- sizeHints.min_height = height;
- sizeHints.max_height = height;
+ XSizeHints* sizeHints = XAllocSizeHints();
+ sizeHints->flags = PMinSize | PMaxSize;
+ sizeHints->min_width = sizeHints->max_width = width;
+ sizeHints->min_height = sizeHints->max_height = height;
+ XSetWMNormalHints(m_display, m_window, sizeHints);
+ XFree(sizeHints);
}
- // Set the WM hints of the normal state
- setWMSizeHints(sizeHints);
-
// Set the window's WM class (this can be used by window managers)
- // The WM_CLASS property actually consists of 2 parts,
- // the instance name and the class name both of which should be
- // null terminated strings.
- // The instance name should be something unique to this invokation
+ XClassHint* hint = XAllocClassHint();
+
+ // The instance name should be something unique to this invocation
// of the application but is rarely if ever used these days.
// For simplicity, we retrieve it via the base executable name.
+ std::string executableName = findExecutableName();
+ std::vector<char> windowInstance(executableName.size() + 1, 0);
+ std::copy(executableName.begin(), executableName.end(), windowInstance.begin());
+ hint->res_name = &windowInstance[0];
+
// The class name identifies a class of windows that
// "are of the same type". We simply use the initial window name as
// the class name.
- std::string windowClass = findExecutableName();
- windowClass += '\0'; // Important to separate instance from class
- windowClass += title.toAnsiString();
+ std::string ansiTitle = title.toAnsiString();
+ std::vector<char> windowClass(ansiTitle.size() + 1, 0);
+ std::copy(ansiTitle.begin(), ansiTitle.end(), windowClass.begin());
+ hint->res_class = &windowClass[0];
+
+ XSetClassHint(m_display, m_window, hint);
- // We add 1 to the size of the string to include the null at the end
- if (!changeWindowProperty(XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8, windowClass.size() + 1, windowClass.c_str()))
- sf::err() << "Failed to set WM_CLASS property" << std::endl;
+ XFree(hint);
// Set the window's name
setTitle(title);
@@ -562,18 +618,27 @@ WindowImplX11::~WindowImplX11()
// Cleanup graphical resources
cleanup();
+ // Destroy icon pixmap
+ if(m_iconPixmap)
+ XFreePixmap(m_display, m_iconPixmap);
+
+ // Destroy icon mask pixmap
+ if(m_iconMaskPixmap)
+ XFreePixmap(m_display, m_iconMaskPixmap);
+
// Destroy the cursor
if (m_hiddenCursor)
- xcb_free_cursor(m_connection, m_hiddenCursor);
+ XFreeCursor(m_display, m_hiddenCursor);
// Destroy the input context
if (m_inputContext)
XDestroyIC(m_inputContext);
+
// Destroy the window
if (m_window && !m_isExternal)
{
- xcb_destroy_window(m_connection, m_window);
- xcb_flush(m_connection);
+ XDestroyWindow(m_display, m_window);
+ XFlush(m_display);
}
// Close the input method
@@ -610,70 +675,31 @@ void WindowImplX11::processEvents()
////////////////////////////////////////////////////////////
Vector2i WindowImplX11::getPosition() const
{
- ::Window topLevelWindow = m_window;
- ::Window nextWindow = topLevelWindow;
+ ::Window root, child;
+ int localX, localY, x, y;
+ unsigned int width, height, border, depth;
- ScopedXcbPtr<xcb_generic_error_t> error(NULL);
+ XGetGeometry(m_display, m_window, &root, &localX, &localY, &width, &height, &border, &depth);
+ XTranslateCoordinates(m_display, m_window, root, localX, localY, &x, &y, &child);
- // Get "top level" window, i.e. the window with the root window as its parent.
- while (nextWindow != m_screen->root)
- {
- topLevelWindow = nextWindow;
-
- ScopedXcbPtr<xcb_query_tree_reply_t> treeReply(xcb_query_tree_reply(
- m_connection,
- xcb_query_tree(
- m_connection,
- topLevelWindow
- ),
- &error
- ));
-
- if (error)
- {
- err() << "Failed to get window position (query_tree)" << std::endl;
- return Vector2i(0, 0);
- }
-
- nextWindow = treeReply->parent;
- }
-
- ScopedXcbPtr<xcb_get_geometry_reply_t> geometryReply(xcb_get_geometry_reply(
- m_connection,
- xcb_get_geometry(
- m_connection,
- topLevelWindow
- ),
- &error
- ));
-
- if (error)
- {
- err() << "Failed to get window position (get_geometry)" << std::endl;
- return Vector2i(0, 0);
- }
-
- return Vector2i(geometryReply->x, geometryReply->y);
+ return Vector2i(x, y);
}
////////////////////////////////////////////////////////////
void WindowImplX11::setPosition(const Vector2i& position)
{
- uint32_t values[] = {static_cast<uint32_t>(position.x), static_cast<uint32_t>(position.y)};
- xcb_configure_window(m_connection, m_window,
- XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
- values);
- xcb_flush(m_connection);
+ XMoveWindow(m_display, m_window, position.x, position.y);
+ XFlush(m_display);
}
////////////////////////////////////////////////////////////
Vector2u WindowImplX11::getSize() const
{
- ScopedXcbPtr<xcb_get_geometry_reply_t> reply(xcb_get_geometry_reply(m_connection, xcb_get_geometry(m_connection, m_window), NULL));
-
- return Vector2u(reply->width, reply->height);
+ XWindowAttributes attributes;
+ XGetWindowAttributes(m_display, m_window, &attributes);
+ return Vector2u(attributes.width, attributes.height);
}
@@ -681,75 +707,65 @@ Vector2u WindowImplX11::getSize() const
void WindowImplX11::setSize(const Vector2u& size)
{
// If resizing is disable for the window we have to update the size hints (required by some window managers).
- if( m_useSizeHints ) {
- WMSizeHints sizeHints;
- std::memset(&sizeHints, 0, sizeof(sizeHints));
-
- sizeHints.flags |= (1 << 4 | 1 << 5);
- sizeHints.min_width = size.x;
- sizeHints.max_width = size.x;
- sizeHints.min_height = size.y;
- sizeHints.max_height = size.y;
-
- setWMSizeHints(sizeHints);
+ if (m_useSizeHints)
+ {
+ XSizeHints* sizeHints = XAllocSizeHints();
+ sizeHints->flags = PMinSize | PMaxSize;
+ sizeHints->min_width = sizeHints->max_width = size.x;
+ sizeHints->min_height = sizeHints->max_height = size.y;
+ XSetWMNormalHints(m_display, m_window, sizeHints);
+ XFree(sizeHints);
}
- uint32_t values[] = {size.x, size.y};
-
- ScopedXcbPtr<xcb_generic_error_t> configureWindowError(xcb_request_check(
- m_connection,
- xcb_configure_window(
- m_connection,
- m_window,
- XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
- values
- )
- ));
-
- if (configureWindowError)
- err() << "Failed to set window size" << std::endl;
-
- xcb_flush(m_connection);
+ XResizeWindow(m_display, m_window, size.x, size.y);
+ XFlush(m_display);
}
////////////////////////////////////////////////////////////
void WindowImplX11::setTitle(const String& title)
{
- // XCB takes UTF-8-encoded strings.
- xcb_atom_t utf8StringType = getAtom("UTF8_STRING");
-
- if (!utf8StringType)
- utf8StringType = XCB_ATOM_STRING;
-
- std::string utf8String;
- Utf<32>::toUtf8(title.begin(), title.end(), std::back_inserter(utf8String));
-
- if (!changeWindowProperty(XCB_ATOM_WM_NAME, utf8StringType, 8, utf8String.length(), utf8String.c_str()))
- err() << "Failed to set window title" << std::endl;
-
- if (!changeWindowProperty(XCB_ATOM_WM_ICON_NAME, utf8StringType, 8, utf8String.length(), utf8String.c_str()))
- err() << "Failed to set WM_ICON_NAME property" << std::endl;
-
- if (ewmhSupported())
- {
- xcb_atom_t netWmName = getAtom("_NET_WM_NAME", true);
- xcb_atom_t netWmIconName = getAtom("_NET_WM_ICON_NAME", true);
-
- if (utf8StringType && netWmName)
- {
- if (!changeWindowProperty(netWmName, utf8StringType, 8, utf8String.length(), utf8String.c_str()))
- err() << "Failed to set _NET_WM_NAME property" << std::endl;
- }
-
- if (utf8StringType && netWmIconName)
- {
- if (!changeWindowProperty(netWmIconName, utf8StringType, 8, utf8String.length(), utf8String.c_str()))
- err() << "Failed to set _NET_WM_ICON_NAME property" << std::endl;
- }
- }
-
- xcb_flush(m_connection);
+ // Bare X11 has no Unicode window title support.
+ // There is however an option to tell the window manager your Unicode title via hints.
+
+ // Convert to UTF-8 encoding.
+ std::basic_string<Uint8> utf8Title;
+ Utf32::toUtf8(title.begin(), title.end(), std::back_inserter(utf8Title));
+
+ Atom useUtf8 = getAtom("UTF8_STRING", false);
+
+ // Set the _NET_WM_NAME atom, which specifies a UTF-8 encoded window title.
+ Atom wmName = getAtom("_NET_WM_NAME", false);
+ XChangeProperty(m_display, m_window, wmName, useUtf8, 8,
+ PropModeReplace, utf8Title.c_str(), utf8Title.size());
+
+ // Set the _NET_WM_ICON_NAME atom, which specifies a UTF-8 encoded window title.
+ Atom wmIconName = getAtom("_NET_WM_ICON_NAME", false);
+ XChangeProperty(m_display, m_window, wmIconName, useUtf8, 8,
+ PropModeReplace, utf8Title.c_str(), utf8Title.size());
+
+ // Set the non-Unicode title as a fallback for window managers who don't support _NET_WM_NAME.
+ #ifdef X_HAVE_UTF8_STRING
+ Xutf8SetWMProperties(m_display,
+ m_window,
+ title.toAnsiString().c_str(),
+ title.toAnsiString().c_str(),
+ NULL,
+ 0,
+ NULL,
+ NULL,
+ NULL);
+ #else
+ XmbSetWMProperties(m_display,
+ m_window,
+ title.toAnsiString().c_str(),
+ title.toAnsiString().c_str(),
+ NULL,
+ 0,
+ NULL,
+ NULL,
+ NULL);
+ #endif
}
@@ -757,99 +773,42 @@ void WindowImplX11::setTitle(const String& title)
void WindowImplX11::setIcon(unsigned int width, unsigned int height, const Uint8* pixels)
{
// X11 wants BGRA pixels: swap red and blue channels
- Uint8 iconPixels[width * height * 4];
+ // Note: this memory will be freed by XDestroyImage
+ Uint8* iconPixels = static_cast<Uint8*>(std::malloc(width * height * 4));
for (std::size_t i = 0; i < width * height; ++i)
{
- iconPixels[i * 4 + 0] = pixels[i * 4 + 2];
- iconPixels[i * 4 + 1] = pixels[i * 4 + 1];
- iconPixels[i * 4 + 2] = pixels[i * 4 + 0];
- iconPixels[i * 4 + 3] = pixels[i * 4 + 3];
+ iconPixels[8 + i * 4 + 0] = pixels[i * 4 + 2];
+ iconPixels[8 + i * 4 + 1] = pixels[i * 4 + 1];
+ iconPixels[8 + i * 4 + 2] = pixels[i * 4 + 0];
+ iconPixels[8 + i * 4 + 3] = pixels[i * 4 + 3];
}
// Create the icon pixmap
- xcb_pixmap_t iconPixmap = xcb_generate_id(m_connection);
-
- ScopedXcbPtr<xcb_generic_error_t> createPixmapError(xcb_request_check(
- m_connection,
- xcb_create_pixmap_checked(
- m_connection,
- m_screen->root_depth,
- iconPixmap,
- m_screen->root,
- width,
- height
- )
- ));
-
- if (createPixmapError)
+ Visual* defVisual = DefaultVisual(m_display, m_screen);
+ unsigned int defDepth = DefaultDepth(m_display, m_screen);
+ XImage* iconImage = XCreateImage(m_display, defVisual, defDepth, ZPixmap, 0, (char*)iconPixels, width, height, 32, 0);
+ if (!iconImage)
{
- err() << "Failed to set the window's icon (create_pixmap): ";
- err() << "Error code " << static_cast<int>(createPixmapError->error_code) << std::endl;
+ err() << "Failed to set the window's icon" << std::endl;
return;
}
- xcb_gcontext_t iconGC = xcb_generate_id(m_connection);
-
- ScopedXcbPtr<xcb_generic_error_t> createGcError(xcb_request_check(
- m_connection,
- xcb_create_gc(
- m_connection,
- iconGC,
- iconPixmap,
- 0,
- NULL
- )
- ));
-
- if (createGcError)
- {
- err() << "Failed to set the window's icon (create_gc): ";
- err() << "Error code " << static_cast<int>(createGcError->error_code) << std::endl;
- return;
- }
+ if(m_iconPixmap)
+ XFreePixmap(m_display, m_iconPixmap);
- ScopedXcbPtr<xcb_generic_error_t> putImageError(xcb_request_check(
- m_connection,
- xcb_put_image_checked(
- m_connection,
- XCB_IMAGE_FORMAT_Z_PIXMAP,
- iconPixmap,
- iconGC,
- width,
- height,
- 0,
- 0,
- 0,
- m_screen->root_depth,
- sizeof(iconPixels),
- iconPixels
- )
- ));
-
- ScopedXcbPtr<xcb_generic_error_t> freeGcError(xcb_request_check(
- m_connection,
- xcb_free_gc(
- m_connection,
- iconGC
- )
- ));
-
- if (freeGcError)
- {
- err() << "Failed to free icon GC: ";
- err() << "Error code " << static_cast<int>(freeGcError->error_code) << std::endl;
- }
+ if(m_iconMaskPixmap)
+ XFreePixmap(m_display, m_iconMaskPixmap);
- if (putImageError)
- {
- err() << "Failed to set the window's icon (put_image): ";
- err() << "Error code " << static_cast<int>(putImageError->error_code) << std::endl;
- return;
- }
+ m_iconPixmap = XCreatePixmap(m_display, RootWindow(m_display, m_screen), width, height, defDepth);
+ XGCValues values;
+ GC iconGC = XCreateGC(m_display, m_iconPixmap, 0, &values);
+ XPutImage(m_display, m_iconPixmap, iconGC, iconImage, 0, 0, 0, 0, width, height);
+ XFreeGC(m_display, iconGC);
+ XDestroyImage(iconImage);
// Create the mask pixmap (must have 1 bit depth)
std::size_t pitch = (width + 7) / 8;
- static std::vector<Uint8> maskPixels(pitch * height, 0);
+ std::vector<Uint8> maskPixels(pitch * height, 0);
for (std::size_t j = 0; j < height; ++j)
{
for (std::size_t i = 0; i < pitch; ++i)
@@ -864,43 +823,42 @@ void WindowImplX11::setIcon(unsigned int width, unsigned int height, const Uint8
}
}
}
-
- xcb_pixmap_t maskPixmap = xcb_create_pixmap_from_bitmap_data(
- m_connection,
- m_window,
- reinterpret_cast<uint8_t*>(&maskPixels[0]),
- width,
- height,
- 1,
- 0,
- 1,
- NULL
- );
+ m_iconMaskPixmap = XCreatePixmapFromBitmapData(m_display, m_window, (char*)&maskPixels[0], width, height, 1, 0, 1);
// Send our new icon to the window through the WMHints
- WMHints hints;
- std::memset(&hints, 0, sizeof(hints));
- hints.flags |= ((1 << 2) | (1 << 5));
- hints.icon_pixmap = iconPixmap;
- hints.icon_mask = maskPixmap;
-
- setWMHints(hints);
+ XWMHints* hints = XAllocWMHints();
+ hints->flags = IconPixmapHint | IconMaskHint;
+ hints->icon_pixmap = m_iconPixmap;
+ hints->icon_mask = m_iconMaskPixmap;
+ XSetWMHints(m_display, m_window, hints);
+ XFree(hints);
+
+ // ICCCM wants BGRA pixels: swap red and blue channels
+ // ICCCM also wants the first 2 unsigned 32-bit values to be width and height
+ std::vector<Uint8> icccmIconPixels(8 + width * height * 4, 0);
+ for (std::size_t i = 0; i < width * height; ++i)
+ {
+ icccmIconPixels[8 + i * 4 + 0] = pixels[i * 4 + 2];
+ icccmIconPixels[8 + i * 4 + 1] = pixels[i * 4 + 1];
+ icccmIconPixels[8 + i * 4 + 2] = pixels[i * 4 + 0];
+ icccmIconPixels[8 + i * 4 + 3] = pixels[i * 4 + 3];
+ }
- xcb_flush(m_connection);
+ reinterpret_cast<Uint32*>(&icccmIconPixels[0])[0] = width;
+ reinterpret_cast<Uint32*>(&icccmIconPixels[0])[1] = height;
- ScopedXcbPtr<xcb_generic_error_t> freePixmapError(xcb_request_check(
- m_connection,
- xcb_free_pixmap_checked(
- m_connection,
- iconPixmap
- )
- ));
+ Atom netWmIcon = getAtom("_NET_WM_ICON");
- if (freePixmapError)
- {
- err() << "Failed to free icon pixmap: ";
- err() << "Error code " << static_cast<int>(freePixmapError->error_code) << std::endl;
- }
+ XChangeProperty(m_display,
+ m_window,
+ netWmIcon,
+ XA_CARDINAL,
+ 32,
+ PropModeReplace,
+ reinterpret_cast<const unsigned char*>(&icccmIconPixels[0]),
+ 2 + width * height);
+
+ XFlush(m_display);
}
@@ -909,42 +867,24 @@ void WindowImplX11::setVisible(bool visible)
{
if (visible)
{
- ScopedXcbPtr<xcb_generic_error_t> error(xcb_request_check(
- m_connection,
- xcb_map_window(
- m_connection,
- m_window
- )
- ));
-
- if (error)
- err() << "Failed to change window visibility" << std::endl;
+ XMapWindow(m_display, m_window);
- xcb_flush(m_connection);
+ XFlush(m_display);
// Before continuing, make sure the WM has
// internally marked the window as viewable
- while (!m_windowMapped)
+ while (!m_windowMapped && !m_isExternal)
processEvents();
}
else
{
- ScopedXcbPtr<xcb_generic_error_t> error(xcb_request_check(
- m_connection,
- xcb_unmap_window(
- m_connection,
- m_window
- )
- ));
+ XUnmapWindow(m_display, m_window);
- if (error)
- err() << "Failed to change window visibility" << std::endl;
-
- xcb_flush(m_connection);
+ XFlush(m_display);
// Before continuing, make sure the WM has
// internally marked the window as unviewable
- while (m_windowMapped)
+ while (m_windowMapped && !m_isExternal)
processEvents();
}
}
@@ -953,22 +893,8 @@ void WindowImplX11::setVisible(bool visible)
////////////////////////////////////////////////////////////
void WindowImplX11::setMouseCursorVisible(bool visible)
{
- const uint32_t values = visible ? XCB_NONE : m_hiddenCursor;
-
- ScopedXcbPtr<xcb_generic_error_t> error(xcb_request_check(
- m_connection,
- xcb_change_window_attributes(
- m_connection,
- m_window,
- XCB_CW_CURSOR,
- &values
- )
- ));
-
- if (error)
- err() << "Failed to change mouse cursor visibility" << std::endl;
-
- xcb_flush(m_connection);
+ XDefineCursor(m_display, m_window, visible ? None : m_hiddenCursor);
+ XFlush(m_display);
}
@@ -984,25 +910,9 @@ void WindowImplX11::setMouseCursorGrabbed(bool grabbed)
// Try multiple times to grab the cursor
for (unsigned int trial = 0; trial < maxTrialsCount; ++trial)
{
- sf::priv::ScopedXcbPtr<xcb_generic_error_t> error(NULL);
+ int result = XGrabPointer(m_display, m_window, True, None, GrabModeAsync, GrabModeAsync, m_window, None, CurrentTime);
- sf::priv::ScopedXcbPtr<xcb_grab_pointer_reply_t> grabPointerReply(xcb_grab_pointer_reply(
- m_connection,
- xcb_grab_pointer(
- m_connection,
- true,
- m_window,
- XCB_NONE,
- XCB_GRAB_MODE_ASYNC,
- XCB_GRAB_MODE_ASYNC,
- m_window,
- XCB_NONE,
- XCB_CURRENT_TIME
- ),
- &error
- ));
-
- if (!error && grabPointerReply && (grabPointerReply->status == XCB_GRAB_STATUS_SUCCESS))
+ if (result == GrabSuccess)
{
m_cursorGrabbed = true;
break;
@@ -1017,22 +927,7 @@ void WindowImplX11::setMouseCursorGrabbed(bool grabbed)
}
else
{
- ScopedXcbPtr<xcb_generic_error_t> error(xcb_request_check(
- m_connection,
- xcb_ungrab_pointer_checked(
- m_connection,
- XCB_CURRENT_TIME
- )
- ));
-
- if (!error)
- {
- m_cursorGrabbed = false;
- }
- else
- {
- err() << "Failed to ungrab mouse cursor" << std::endl;
- }
+ XUngrabPointer(m_display, CurrentTime);
}
}
@@ -1064,26 +959,16 @@ void WindowImplX11::requestFocus()
}
}
- ScopedXcbPtr<xcb_generic_error_t> error(NULL);
-
// Check if window is viewable (not on other desktop, ...)
// TODO: Check also if minimized
- ScopedXcbPtr<xcb_get_window_attributes_reply_t> attributes(xcb_get_window_attributes_reply(
- m_connection,
- xcb_get_window_attributes(
- m_connection,
- m_window
- ),
- &error
- ));
-
- if (error || !attributes)
+ XWindowAttributes attributes;
+ if (XGetWindowAttributes(m_display, m_window, &attributes) == 0)
{
- err() << "Failed to check if window is viewable while requesting focus" << std::endl;
+ sf::err() << "Failed to check if window is viewable while requesting focus" << std::endl;
return; // error getting attribute
}
- bool windowViewable = (attributes->map_state == XCB_MAP_STATE_VIEWABLE);
+ bool windowViewable = (attributes.map_state == IsViewable);
if (sfmlWindowFocused && windowViewable)
{
@@ -1093,31 +978,16 @@ void WindowImplX11::requestFocus()
}
else
{
- // Get current WM hints.
- ScopedXcbPtr<xcb_get_property_reply_t> hintsReply(xcb_get_property_reply(
- m_connection,
- xcb_get_property(m_connection, 0, m_window, XCB_ATOM_WM_HINTS, XCB_ATOM_WM_HINTS, 0, 9),
- &error
- ));
-
- if (error || !hintsReply)
- {
- err() << "Failed to get WM hints while requesting focus" << std::endl;
- return;
- }
-
- WMHints* hints = reinterpret_cast<WMHints*>(xcb_get_property_value(hintsReply.get()));
-
- if (!hints)
- {
- err() << "Failed to get WM hints while requesting focus" << std::endl;
- return;
- }
-
- // Even if no hints were returned, we can simply set the proper flags we need and go on. This is
- // different from Xlib where XAllocWMHints() has to be called.
- hints->flags |= (1 << 8);
- setWMHints(*hints);
+ // Otherwise: display urgency hint (flashing application logo)
+ // Ensure WM hints exist, allocate if necessary
+ XWMHints* hints = XGetWMHints(m_display, m_window);
+ if (hints == NULL)
+ hints = XAllocWMHints();
+
+ // Add urgency (notification) flag to hints
+ hints->flags |= XUrgencyHint;
+ XSetWMHints(m_display, m_window, hints);
+ XFree(hints);
}
}
@@ -1125,91 +995,59 @@ void WindowImplX11::requestFocus()
////////////////////////////////////////////////////////////
bool WindowImplX11::hasFocus() const
{
- ScopedXcbPtr<xcb_generic_error_t> error(NULL);
+ ::Window focusedWindow = 0;
+ int revertToReturn = 0;
+ XGetInputFocus(m_display, &focusedWindow, &revertToReturn);
- ScopedXcbPtr<xcb_get_input_focus_reply_t> reply(xcb_get_input_focus_reply(
- m_connection,
- xcb_get_input_focus_unchecked(
- m_connection
- ),
- &error
- ));
-
- if (error)
- err() << "Failed to check if window has focus" << std::endl;
-
- return (reply->focus == m_window);
+ return (m_window == focusedWindow);
}
////////////////////////////////////////////////////////////
void WindowImplX11::grabFocus()
{
- xcb_atom_t netActiveWindow = XCB_ATOM_NONE;
+ Atom netActiveWindow = None;
if (ewmhSupported())
netActiveWindow = getAtom("_NET_ACTIVE_WINDOW");
+ // Only try to grab focus if the window is mapped
+ XWindowAttributes attr;
+
+ XGetWindowAttributes(m_display, m_window, &attr);
+
+ if (attr.map_state == IsUnmapped)
+ return;
+
if (netActiveWindow)
{
- xcb_client_message_event_t event;
+ XEvent event;
std::memset(&event, 0, sizeof(event));
- event.response_type = XCB_CLIENT_MESSAGE;
- event.window = m_window;
- event.format = 32;
- event.sequence = 0;
- event.type = netActiveWindow;
- event.data.data32[0] = 1; // Normal application
- event.data.data32[1] = XCB_CURRENT_TIME;
- event.data.data32[2] = 0; // We don't know the currently active window
-
- ScopedXcbPtr<xcb_generic_error_t> activeWindowError(xcb_request_check(
- m_connection,
- xcb_send_event_checked(
- m_connection,
- 0,
- XCBDefaultRootWindow(m_connection),
- XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
- reinterpret_cast<char*>(&event)
- )
- ));
-
- if (activeWindowError)
+ event.type = ClientMessage;
+ event.xclient.window = m_window;
+ event.xclient.format = 32;
+ event.xclient.message_type = netActiveWindow;
+ event.xclient.data.l[0] = 1; // Normal application
+ event.xclient.data.l[1] = m_lastInputTime;
+ event.xclient.data.l[2] = 0; // We don't know the currently active window
+
+ int result = XSendEvent(m_display,
+ DefaultRootWindow(m_display),
+ False,
+ SubstructureNotifyMask | SubstructureRedirectMask,
+ &event);
+
+ XFlush(m_display);
+
+ if (!result)
err() << "Setting fullscreen failed, could not send \"_NET_ACTIVE_WINDOW\" event" << std::endl;
}
else
{
- ScopedXcbPtr<xcb_generic_error_t> setInputFocusError(xcb_request_check(
- m_connection,
- xcb_set_input_focus(
- m_connection,
- XCB_INPUT_FOCUS_POINTER_ROOT,
- m_window,
- XCB_CURRENT_TIME
- )
- ));
-
- if (setInputFocusError)
- {
- err() << "Failed to change active window (set_input_focus)" << std::endl;
- return;
- }
-
- const uint32_t values[] = {XCB_STACK_MODE_ABOVE};
-
- ScopedXcbPtr<xcb_generic_error_t> configureWindowError(xcb_request_check(
- m_connection,
- xcb_configure_window(
- m_connection,
- m_window,
- XCB_CONFIG_WINDOW_STACK_MODE,
- values
- )
- ));
-
- if (configureWindowError)
- err() << "Failed to change active window (configure_window)" << std::endl;
+ XRaiseWindow(m_display, m_window);
+ XSetInputFocus(m_display, m_window, RevertToPointerRoot, CurrentTime);
+ XFlush(m_display);
}
}
@@ -1221,46 +1059,19 @@ void WindowImplX11::setVideoMode(const VideoMode& mode)
if (mode == VideoMode::getDesktopMode())
return;
- ScopedXcbPtr<xcb_generic_error_t> error(NULL);
-
- // Check if the RandR extension is present
- const xcb_query_extension_reply_t* randrExt = xcb_get_extension_data(m_connection, &xcb_randr_id);
-
- if (!randrExt || !randrExt->present)
+ // Check if the XRandR extension is present
+ int version;
+ if (!XQueryExtension(m_display, "RANDR", &version, &version, &version))
{
- // RandR extension is not supported: we cannot use fullscreen mode
+ // XRandR extension is not supported: we cannot use fullscreen mode
err() << "Fullscreen is not supported, switching to window mode" << std::endl;
return;
}
- // Load RandR and check its version
- ScopedXcbPtr<xcb_randr_query_version_reply_t> randrVersion(xcb_randr_query_version_reply(
- m_connection,
- xcb_randr_query_version(
- m_connection,
- 1,
- 1
- ),
- &error
- ));
-
- if (error)
- {
- err() << "Failed to load RandR, switching to window mode" << std::endl;
- return;
- }
-
// Get the current configuration
- ScopedXcbPtr<xcb_randr_get_screen_info_reply_t> config(xcb_randr_get_screen_info_reply(
- m_connection,
- xcb_randr_get_screen_info(
- m_connection,
- m_screen->root
- ),
- &error
- ));
-
- if (error || !config)
+ XRRScreenConfiguration* config = XRRGetScreenInfo(m_display, RootWindow(m_display, m_screen));
+
+ if (!config)
{
// Failed to get the screen configuration
err() << "Failed to get the current screen configuration for fullscreen mode, switching to window mode" << std::endl;
@@ -1268,52 +1079,34 @@ void WindowImplX11::setVideoMode(const VideoMode& mode)
}
// Save the current video mode before we switch to fullscreen
- m_oldVideoMode = *config.get();
+ Rotation currentRotation;
+ m_oldVideoMode = XRRConfigCurrentConfiguration(config, &currentRotation);
// Get the available screen sizes
- xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config.get());
-
- if (!sizes || !config->nSizes)
- {
- err() << "Failed to get the fullscreen sizes, switching to window mode" << std::endl;
- return;
- }
+ int nbSizes;
+ XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes);
// Search for a matching size
- for (int i = 0; i < config->nSizes; ++i)
+ for (int i = 0; (sizes && i < nbSizes); ++i)
{
- if (config->rotation == XCB_RANDR_ROTATION_ROTATE_90 ||
- config->rotation == XCB_RANDR_ROTATION_ROTATE_270)
+ XRRConfigRotations(config, &currentRotation);
+
+ if (currentRotation == RR_Rotate_90 || currentRotation == RR_Rotate_270)
std::swap(sizes[i].height, sizes[i].width);
- if ((sizes[i].width == static_cast<int>(mode.width)) &&
- (sizes[i].height == static_cast<int>(mode.height)))
+ if ((sizes[i].width == static_cast<int>(mode.width)) && (sizes[i].height == static_cast<int>(mode.height)))
{
// Switch to fullscreen mode
- ScopedXcbPtr<xcb_randr_set_screen_config_reply_t> setScreenConfig(xcb_randr_set_screen_config_reply(
- m_connection,
- xcb_randr_set_screen_config(
- m_connection,
- config->root,
- XCB_CURRENT_TIME,
- config->config_timestamp,
- i,
- config->rotation,
- config->rate
- ),
- &error
- ));
-
- if (error)
- err() << "Failed to set new screen configuration" << std::endl;
+ XRRSetScreenConfig(m_display, config, RootWindow(m_display, m_screen), i, currentRotation, CurrentTime);
// Set "this" as the current fullscreen window
fullscreenWindow = this;
- return;
+ break;
}
}
- err() << "Failed to find matching fullscreen size, switching to window mode" << std::endl;
+ // Free the configuration instance
+ XRRFreeScreenConfigInfo(config);
}
@@ -1323,25 +1116,19 @@ void WindowImplX11::resetVideoMode()
if (fullscreenWindow == this)
{
// Get current screen info
- ScopedXcbPtr<xcb_generic_error_t> error(NULL);
-
- // Reset the video mode
- ScopedXcbPtr<xcb_randr_set_screen_config_reply_t> setScreenConfig(xcb_randr_set_screen_config_reply(
- m_connection,
- xcb_randr_set_screen_config(
- m_connection,
- m_oldVideoMode.root,
- XCB_CURRENT_TIME,
- m_oldVideoMode.config_timestamp,
- m_oldVideoMode.sizeID,
- m_oldVideoMode.rotation,
- m_oldVideoMode.rate
- ),
- &error
- ));
-
- if (error)
- err() << "Failed to reset old screen configuration" << std::endl;
+ XRRScreenConfiguration* config = XRRGetScreenInfo(m_display, RootWindow(m_display, m_screen));
+ if (config)
+ {
+ // Get the current rotation
+ Rotation currentRotation;
+ XRRConfigCurrentConfiguration(config, &currentRotation);
+
+ // Reset the video mode
+ XRRSetScreenConfig(m_display, config, RootWindow(m_display, m_screen), m_oldVideoMode, currentRotation, CurrentTime);
+
+ // Free the configuration instance
+ XRRFreeScreenConfigInfo(config);
+ }
// Reset the fullscreen window
fullscreenWindow = NULL;
@@ -1356,19 +1143,24 @@ void WindowImplX11::switchToFullscreen()
if (ewmhSupported())
{
- xcb_atom_t netWmBypassCompositor = getAtom("_NET_WM_BYPASS_COMPOSITOR");
+ Atom netWmBypassCompositor = getAtom("_NET_WM_BYPASS_COMPOSITOR");
if (netWmBypassCompositor)
{
static const Uint32 bypassCompositor = 1;
- // Not being able to bypass the compositor is not a fatal error
- if (!changeWindowProperty(netWmBypassCompositor, XCB_ATOM_CARDINAL, 32, 1, &bypassCompositor))
- err() << "xcb_change_property failed, unable to set _NET_WM_BYPASS_COMPOSITOR" << std::endl;
+ XChangeProperty(m_display,
+ m_window,
+ netWmBypassCompositor,
+ XA_CARDINAL,
+ 32,
+ PropModeReplace,
+ reinterpret_cast<const unsigned char*>(&bypassCompositor),
+ 1);
}
- xcb_atom_t netWmState = getAtom("_NET_WM_STATE", true);
- xcb_atom_t netWmStateFullscreen = getAtom("_NET_WM_STATE_FULLSCREEN", true);
+ Atom netWmState = getAtom("_NET_WM_STATE", true);
+ Atom netWmStateFullscreen = getAtom("_NET_WM_STATE_FULLSCREEN", true);
if (!netWmState || !netWmStateFullscreen)
{
@@ -1376,32 +1168,26 @@ void WindowImplX11::switchToFullscreen()
return;
}
- xcb_client_message_event_t event;
+ XEvent event;
std::memset(&event, 0, sizeof(event));
- event.response_type = XCB_CLIENT_MESSAGE;
- event.window = m_window;
- event.format = 32;
- event.sequence = 0;
- event.type = netWmState;
- event.data.data32[0] = 1; // _NET_WM_STATE_ADD
- event.data.data32[1] = netWmStateFullscreen;
- event.data.data32[2] = 0; // No second property
- event.data.data32[3] = 1; // Normal window
-
- ScopedXcbPtr<xcb_generic_error_t> wmStateError(xcb_request_check(
- m_connection,
- xcb_send_event_checked(
- m_connection,
- 0,
- XCBDefaultRootWindow(m_connection),
- XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
- reinterpret_cast<char*>(&event)
- )
- ));
-
- if (wmStateError)
- err() << "Setting fullscreen failed. Could not send \"_NET_WM_STATE\" event" << std::endl;
+ event.type = ClientMessage;
+ event.xclient.window = m_window;
+ event.xclient.format = 32;
+ event.xclient.message_type = netWmState;
+ event.xclient.data.l[0] = 1; // _NET_WM_STATE_ADD
+ event.xclient.data.l[1] = netWmStateFullscreen;
+ event.xclient.data.l[2] = 0; // No second property
+ event.xclient.data.l[3] = 1; // Normal window
+
+ int result = XSendEvent(m_display,
+ DefaultRootWindow(m_display),
+ False,
+ SubstructureNotifyMask | SubstructureRedirectMask,
+ &event);
+
+ if (!result)
+ err() << "Setting fullscreen failed, could not send \"_NET_WM_STATE\" event" << std::endl;
}
}
@@ -1409,8 +1195,8 @@ void WindowImplX11::switchToFullscreen()
////////////////////////////////////////////////////////////
void WindowImplX11::setProtocols()
{
- xcb_atom_t wmProtocols = getAtom("WM_PROTOCOLS");
- xcb_atom_t wmDeleteWindow = getAtom("WM_DELETE_WINDOW");
+ Atom wmProtocols = getAtom("WM_PROTOCOLS");
+ Atom wmDeleteWindow = getAtom("WM_DELETE_WINDOW");
if (!wmProtocols)
{
@@ -1418,7 +1204,7 @@ void WindowImplX11::setProtocols()
return;
}
- std::vector<xcb_atom_t> atoms;
+ std::vector<Atom> atoms;
if (wmDeleteWindow)
{
@@ -1429,8 +1215,8 @@ void WindowImplX11::setProtocols()
err() << "Failed to request WM_DELETE_WINDOW atom." << std::endl;
}
- xcb_atom_t netWmPing = XCB_ATOM_NONE;
- xcb_atom_t netWmPid = XCB_ATOM_NONE;
+ Atom netWmPing = None;
+ Atom netWmPid = None;
if (ewmhSupported())
{
@@ -1438,20 +1224,32 @@ void WindowImplX11::setProtocols()
netWmPid = getAtom("_NET_WM_PID", true);
}
- ScopedXcbPtr<xcb_generic_error_t> error(NULL);
-
if (netWmPing && netWmPid)
{
uint32_t pid = getpid();
- if (changeWindowProperty(netWmPid, XCB_ATOM_CARDINAL, 32, 1, &pid))
- atoms.push_back(netWmPing);
+ XChangeProperty(m_display,
+ m_window,
+ netWmPid,
+ XA_CARDINAL,
+ 32,
+ PropModeReplace,
+ reinterpret_cast<const unsigned char*>(&pid),
+ 1);
+
+ atoms.push_back(netWmPing);
}
if (!atoms.empty())
{
- if (!changeWindowProperty(wmProtocols, XCB_ATOM_ATOM, 32, atoms.size(), &atoms[0]))
- err() << "Failed to set window protocols" << std::endl;
+ XChangeProperty(m_display,
+ m_window,
+ wmProtocols,
+ XA_ATOM,
+ 32,
+ PropModeReplace,
+ reinterpret_cast<const unsigned char*>(&atoms[0]),
+ atoms.size());
}
else
{
@@ -1461,122 +1259,6 @@ void WindowImplX11::setProtocols()
////////////////////////////////////////////////////////////
-void WindowImplX11::setMotifHints(unsigned long style)
-{
- ScopedXcbPtr<xcb_generic_error_t> error(NULL);
-
- static const std::string MOTIF_WM_HINTS = "_MOTIF_WM_HINTS";
- ScopedXcbPtr<xcb_intern_atom_reply_t> hintsAtomReply(xcb_intern_atom_reply(
- m_connection,
- xcb_intern_atom(
- m_connection,
- 0,
- MOTIF_WM_HINTS.size(),
- MOTIF_WM_HINTS.c_str()
- ),
- &error
- ));
-
- if (!error && hintsAtomReply)
- {
- static const unsigned long MWM_HINTS_FUNCTIONS = 1 << 0;
- static const unsigned long MWM_HINTS_DECORATIONS = 1 << 1;
-
- //static const unsigned long MWM_DECOR_ALL = 1 << 0;
- static const unsigned long MWM_DECOR_BORDER = 1 << 1;
- static const unsigned long MWM_DECOR_RESIZEH = 1 << 2;
- static const unsigned long MWM_DECOR_TITLE = 1 << 3;
- static const unsigned long MWM_DECOR_MENU = 1 << 4;
- static const unsigned long MWM_DECOR_MINIMIZE = 1 << 5;
- static const unsigned long MWM_DECOR_MAXIMIZE = 1 << 6;
-
- //static const unsigned long MWM_FUNC_ALL = 1 << 0;
- static const unsigned long MWM_FUNC_RESIZE = 1 << 1;
- static const unsigned long MWM_FUNC_MOVE = 1 << 2;
- static const unsigned long MWM_FUNC_MINIMIZE = 1 << 3;
- static const unsigned long MWM_FUNC_MAXIMIZE = 1 << 4;
- static const unsigned long MWM_FUNC_CLOSE = 1 << 5;
-
- struct MotifWMHints
- {
- uint32_t flags;
- uint32_t functions;
- uint32_t decorations;
- int32_t inputMode;
- uint32_t state;
- };
-
- MotifWMHints hints;
- hints.flags = MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS;
- hints.decorations = 0;
- hints.functions = 0;
- hints.inputMode = 0;
- hints.state = 0;
-
- if (style & Style::Titlebar)
- {
- hints.decorations |= MWM_DECOR_BORDER | MWM_DECOR_TITLE | MWM_DECOR_MINIMIZE | MWM_DECOR_MENU;
- hints.functions |= MWM_FUNC_MOVE | MWM_FUNC_MINIMIZE;
- }
- if (style & Style::Resize)
- {
- hints.decorations |= MWM_DECOR_MAXIMIZE | MWM_DECOR_RESIZEH;
- hints.functions |= MWM_FUNC_MAXIMIZE | MWM_FUNC_RESIZE;
- }
- if (style & Style::Close)
- {
- hints.decorations |= 0;
- hints.functions |= MWM_FUNC_CLOSE;
- }
-
- if (!changeWindowProperty(hintsAtomReply->atom, hintsAtomReply->atom, 32, 5, &hints))
- err() << "xcb_change_property failed, could not set window hints" << std::endl;
- }
- else
- {
- err() << "Failed to request _MOTIF_WM_HINTS atom." << std::endl;
- }
-}
-
-
-////////////////////////////////////////////////////////////
-void WindowImplX11::setWMHints(const WMHints& hints)
-{
- if (!changeWindowProperty(XCB_ATOM_WM_HINTS, XCB_ATOM_WM_HINTS, 32, sizeof(hints) / 4, &hints))
- sf::err() << "Failed to set WM_HINTS property" << std::endl;
-}
-
-
-////////////////////////////////////////////////////////////
-void WindowImplX11::setWMSizeHints(const WMSizeHints& hints)
-{
- if (!changeWindowProperty(XCB_ATOM_WM_NORMAL_HINTS, XCB_ATOM_WM_SIZE_HINTS, 32, sizeof(hints) / 4, &hints))
- sf::err() << "Failed to set XCB_ATOM_WM_NORMAL_HINTS property" << std::endl;
-}
-
-
-////////////////////////////////////////////////////////////
-bool WindowImplX11::changeWindowProperty(xcb_atom_t property, xcb_atom_t type, uint8_t format, uint32_t length, const void* data)
-{
- ScopedXcbPtr<xcb_generic_error_t> error(xcb_request_check(
- m_connection,
- xcb_change_property_checked(
- m_connection,
- XCB_PROP_MODE_REPLACE,
- m_window,
- property,
- type,
- format,
- length,
- data
- )
- ));
-
- return !error;
-}
-
-
-////////////////////////////////////////////////////////////
void WindowImplX11::initialize()
{
// Create the input context
@@ -1584,16 +1266,14 @@ void WindowImplX11::initialize()
if (m_inputMethod)
{
- m_inputContext = XCreateIC(
- m_inputMethod,
- XNClientWindow,
- m_window,
- XNFocusWindow,
- m_window,
- XNInputStyle,
- XIMPreeditNothing | XIMStatusNothing,
- reinterpret_cast<void*>(NULL)
- );
+ m_inputContext = XCreateIC(m_inputMethod,
+ XNClientWindow,
+ m_window,
+ XNFocusWindow,
+ m_window,
+ XNInputStyle,
+ XIMPreeditNothing | XIMStatusNothing,
+ reinterpret_cast<void*>(NULL));
}
else
{
@@ -1603,6 +1283,21 @@ void WindowImplX11::initialize()
if (!m_inputContext)
err() << "Failed to create input context for window -- TextEntered event won't be able to return unicode" << std::endl;
+ Atom wmWindowType = getAtom("_NET_WM_WINDOW_TYPE", false);
+ Atom wmWindowTypeNormal = getAtom("_NET_WM_WINDOW_TYPE_NORMAL", false);
+
+ if (wmWindowType && wmWindowTypeNormal)
+ {
+ XChangeProperty(m_display,
+ m_window,
+ wmWindowType,
+ XA_ATOM,
+ 32,
+ PropModeReplace,
+ reinterpret_cast<const unsigned char*>(&wmWindowTypeNormal),
+ 1);
+ }
+
// Show the window
setVisible(true);
@@ -1613,7 +1308,7 @@ void WindowImplX11::initialize()
createHiddenCursor();
// Flush the commands queue
- xcb_flush(m_connection);
+ XFlush(m_display);
// Add this window to the global list of windows (required for focus request)
Lock lock(allWindowsMutex);
@@ -1622,60 +1317,46 @@ void WindowImplX11::initialize()
////////////////////////////////////////////////////////////
-void WindowImplX11::createHiddenCursor()
+void WindowImplX11::updateLastInputTime(::Time time)
{
- xcb_pixmap_t cursorPixmap = xcb_generate_id(m_connection);
-
- // Create the cursor's pixmap (1x1 pixels)
- ScopedXcbPtr<xcb_generic_error_t> createPixmapError(xcb_request_check(
- m_connection,
- xcb_create_pixmap(
- m_connection,
- 1,
- cursorPixmap,
- m_window,
- 1,
- 1
- )
- ));
-
- if (createPixmapError)
+ if (time && (time != m_lastInputTime))
{
- err() << "Failed to create pixmap for hidden cursor" << std::endl;
- return;
+ Atom netWmUserTime = getAtom("_NET_WM_USER_TIME", true);
+
+ if(netWmUserTime)
+ {
+ XChangeProperty(m_display,
+ m_window,
+ netWmUserTime,
+ XA_CARDINAL,
+ 32,
+ PropModeReplace,
+ reinterpret_cast<const unsigned char*>(&time),
+ 1);
+ }
+
+ m_lastInputTime = time;
}
+}
- m_hiddenCursor = xcb_generate_id(m_connection);
+
+////////////////////////////////////////////////////////////
+void WindowImplX11::createHiddenCursor()
+{
+ // Create the cursor's pixmap (1x1 pixels)
+ Pixmap cursorPixmap = XCreatePixmap(m_display, m_window, 1, 1, 1);
+ GC graphicsContext = XCreateGC(m_display, cursorPixmap, 0, NULL);
+ XDrawPoint(m_display, cursorPixmap, graphicsContext, 0, 0);
+ XFreeGC(m_display, graphicsContext);
// Create the cursor, using the pixmap as both the shape and the mask of the cursor
- ScopedXcbPtr<xcb_generic_error_t> createCursorError(xcb_request_check(
- m_connection,
- xcb_create_cursor(
- m_connection,
- m_hiddenCursor,
- cursorPixmap,
- cursorPixmap,
- 0, 0, 0, // Foreground RGB color
- 0, 0, 0, // Background RGB color
- 0, // X
- 0 // Y
- )
- ));
-
- if (createCursorError)
- err() << "Failed to create hidden cursor" << std::endl;
+ XColor color;
+ color.flags = DoRed | DoGreen | DoBlue;
+ color.red = color.blue = color.green = 0;
+ m_hiddenCursor = XCreatePixmapCursor(m_display, cursorPixmap, cursorPixmap, &color, &color, 0, 0);
// We don't need the pixmap any longer, free it
- ScopedXcbPtr<xcb_generic_error_t> freePixmapError(xcb_request_check(
- m_connection,
- xcb_free_pixmap(
- m_connection,
- cursorPixmap
- )
- ));
-
- if (freePixmapError)
- err() << "Failed to free pixmap for hidden cursor" << std::endl;
+ XFreePixmap(m_display, cursorPixmap);
}
@@ -1752,25 +1433,9 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
// Try multiple times to grab the cursor
for (unsigned int trial = 0; trial < maxTrialsCount; ++trial)
{
- sf::priv::ScopedXcbPtr<xcb_generic_error_t> error(NULL);
-
- sf::priv::ScopedXcbPtr<xcb_grab_pointer_reply_t> grabPointerReply(xcb_grab_pointer_reply(
- m_connection,
- xcb_grab_pointer(
- m_connection,
- true,
- m_window,
- XCB_NONE,
- XCB_GRAB_MODE_ASYNC,
- XCB_GRAB_MODE_ASYNC,
- m_window,
- XCB_NONE,
- XCB_CURRENT_TIME
- ),
- &error
- ));
+ int result = XGrabPointer(m_display, m_window, True, None, GrabModeAsync, GrabModeAsync, m_window, None, CurrentTime);
- if (!error && grabPointerReply && (grabPointerReply->status == XCB_GRAB_STATUS_SUCCESS))
+ if (result == GrabSuccess)
{
m_cursorGrabbed = true;
break;
@@ -1789,33 +1454,15 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
pushEvent(event);
// If the window has been previously marked urgent (notification) as a result of a focus request, undo that
- ScopedXcbPtr<xcb_generic_error_t> error(NULL);
-
- ScopedXcbPtr<xcb_get_property_reply_t> hintsReply(xcb_get_property_reply(
- m_connection,
- xcb_get_property(m_connection, 0, m_window, XCB_ATOM_WM_HINTS, XCB_ATOM_WM_HINTS, 0, 9),
- &error
- ));
-
- if (error || !hintsReply)
+ XWMHints* hints = XGetWMHints(m_display, m_window);
+ if (hints != NULL)
{
- err() << "Failed to get WM hints in XCB_FOCUS_IN" << std::endl;
- break;
+ // Remove urgency (notification) flag from hints
+ hints->flags &= ~XUrgencyHint;
+ XSetWMHints(m_display, m_window, hints);
+ XFree(hints);
}
- WMHints* hints = reinterpret_cast<WMHints*>(xcb_get_property_value(hintsReply.get()));
-
- if (!hints)
- {
- err() << "Failed to get WM hints in XCB_FOCUS_IN" << std::endl;
- break;
- }
-
- // Remove urgency (notification) flag from hints
- hints->flags &= ~(1 << 8);
-
- setWMHints(*hints);
-
break;
}
@@ -1828,18 +1475,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
// Release cursor
if (m_cursorGrabbed)
- {
- ScopedXcbPtr<xcb_generic_error_t> error(xcb_request_check(
- m_connection,
- xcb_ungrab_pointer_checked(
- m_connection,
- XCB_CURRENT_TIME
- )
- ));
-
- if (error)
- err() << "Failed to ungrab mouse cursor" << std::endl;
- }
+ XUngrabPointer(m_display, CurrentTime);
Event event;
event.type = Event::LostFocus;
@@ -1868,13 +1504,13 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
// Close event
case ClientMessage:
{
- static xcb_atom_t wmProtocols = getAtom("WM_PROTOCOLS");
+ static Atom wmProtocols = getAtom("WM_PROTOCOLS");
// Handle window manager protocol messages we support
if (windowEvent.xclient.message_type == wmProtocols)
{
- static xcb_atom_t wmDeleteWindow = getAtom("WM_DELETE_WINDOW");
- static xcb_atom_t netWmPing = ewmhSupported() ? getAtom("_NET_WM_PING", true) : XCB_ATOM_NONE;
+ static Atom wmDeleteWindow = getAtom("WM_DELETE_WINDOW");
+ static Atom netWmPing = ewmhSupported() ? getAtom("_NET_WM_PING", true) : None;
if ((windowEvent.xclient.format == 32) && (windowEvent.xclient.data.l[0]) == static_cast<long>(wmDeleteWindow))
{
@@ -1886,9 +1522,9 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
else if (netWmPing && (windowEvent.xclient.format == 32) && (windowEvent.xclient.data.l[0]) == static_cast<long>(netWmPing))
{
// Handle the _NET_WM_PING message, send pong back to WM to show that we are responsive
- windowEvent.xclient.window = XCBDefaultRootWindow(m_connection);
+ windowEvent.xclient.window = DefaultRootWindow(m_display);
- XSendEvent(m_display, windowEvent.xclient.window, False, SubstructureNotifyMask | SubstructureRedirectMask, &windowEvent);
+ XSendEvent(m_display, DefaultRootWindow(m_display), False, SubstructureNotifyMask | SubstructureRedirectMask, &windowEvent);
}
}
break;
@@ -1966,6 +1602,8 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
}
}
+ updateLastInputTime(windowEvent.xkey.time);
+
break;
}
@@ -2023,6 +1661,9 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
}
pushEvent(event);
}
+
+ updateLastInputTime(windowEvent.xbutton.time);
+
break;
}
@@ -2144,6 +1785,15 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
break;
}
+
+ // Window property change
+ case PropertyNotify:
+ {
+ if (!m_lastInputTime)
+ m_lastInputTime = windowEvent.xproperty.time;
+
+ break;
+ }
}
return true;
diff --git a/src/SFML/Window/Unix/WindowImplX11.hpp b/src/SFML/Window/Unix/WindowImplX11.hpp
index ea6f741..fd2295e 100644
--- a/src/SFML/Window/Unix/WindowImplX11.hpp
+++ b/src/SFML/Window/Unix/WindowImplX11.hpp
@@ -31,8 +31,7 @@
#include <SFML/Window/Event.hpp>
#include <SFML/Window/WindowImpl.hpp>
#include <SFML/System/String.hpp>
-#include <X11/Xlib-xcb.h>
-#include <xcb/randr.h>
+#include <X11/Xlib.h>
#include <deque>
@@ -188,33 +187,6 @@ protected:
private:
- struct WMHints
- {
- int32_t flags;
- uint32_t input;
- int32_t initial_state;
- xcb_pixmap_t icon_pixmap;
- xcb_window_t icon_window;
- int32_t icon_x;
- int32_t icon_y;
- xcb_pixmap_t icon_mask;
- xcb_window_t window_group;
- };
-
- struct WMSizeHints
- {
- uint32_t flags;
- int32_t x, y;
- int32_t width, height;
- int32_t min_width, min_height;
- int32_t max_width, max_height;
- int32_t width_inc, height_inc;
- int32_t min_aspect_num, min_aspect_den;
- int32_t max_aspect_num, max_aspect_den;
- int32_t base_width, base_height;
- uint32_t win_gravity;
- };
-
////////////////////////////////////////////////////////////
/// \brief Request the WM to make the current window active
///
@@ -248,40 +220,12 @@ private:
void setProtocols();
////////////////////////////////////////////////////////////
- /// \brief Set Motif WM hints
- ///
- ////////////////////////////////////////////////////////////
- void setMotifHints(unsigned long style);
-
- ////////////////////////////////////////////////////////////
- /// \brief Set WM hints
- ///
- /// \param hints Hints
- ///
- ////////////////////////////////////////////////////////////
- void setWMHints(const WMHints& hints);
-
- ////////////////////////////////////////////////////////////
- /// \brief Set WM size hints
- ///
- /// \param hints Size hints
- ///
- ////////////////////////////////////////////////////////////
- void setWMSizeHints(const WMSizeHints& hints);
-
- ////////////////////////////////////////////////////////////
- /// \brief Change a XCB window property
- ///
- /// \param property Property to change
- /// \param type Type of the property
- /// \param format Format of the property
- /// \param length Length of the new value
- /// \param data The new value of the property
+ /// \brief Update the last time we received user input
///
- /// \return True if successful, false if unsuccessful
+ /// \param time Last time we received user input
///
////////////////////////////////////////////////////////////
- bool changeWindowProperty(xcb_atom_t property, xcb_atom_t type, uint8_t format, uint32_t length, const void* data);
+ void updateLastInputTime(::Time time);
////////////////////////////////////////////////////////////
/// \brief Do some common initializations after the window has been created
@@ -314,21 +258,23 @@ private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
- xcb_window_t m_window; ///< xcb identifier defining our window
- ::Display* m_display; ///< Pointer to the display
- xcb_connection_t* m_connection; ///< Pointer to the xcb connection
- xcb_screen_t* m_screen; ///< Screen identifier
- XIM m_inputMethod; ///< Input method linked to the X display
- XIC m_inputContext; ///< Input context used to get unicode input in our window
- bool m_isExternal; ///< Tell whether the window has been created externally or by SFML
- xcb_randr_get_screen_info_reply_t m_oldVideoMode; ///< Video mode in use before we switch to fullscreen
- Cursor m_hiddenCursor; ///< As X11 doesn't provide cursor hidding, we must create a transparent one
- bool m_keyRepeat; ///< Is the KeyRepeat feature enabled?
- Vector2i m_previousSize; ///< Previous size of the window, to find if a ConfigureNotify event is a resize event (could be a move event only)
- bool m_useSizeHints; ///< Is the size of the window fixed with size hints?
- bool m_fullscreen; ///< Is the window in fullscreen?
- bool m_cursorGrabbed; ///< Is the mouse cursor trapped?
- bool m_windowMapped; ///< Has the window been mapped by the window manager?
+ ::Window m_window; ///< X identifier defining our window
+ ::Display* m_display; ///< Pointer to the display
+ int m_screen; ///< Screen identifier
+ XIM m_inputMethod; ///< Input method linked to the X display
+ XIC m_inputContext; ///< Input context used to get unicode input in our window
+ bool m_isExternal; ///< Tell whether the window has been created externally or by SFML
+ int m_oldVideoMode; ///< Video mode in use before we switch to fullscreen
+ Cursor m_hiddenCursor; ///< As X11 doesn't provide cursor hidding, we must create a transparent one
+ bool m_keyRepeat; ///< Is the KeyRepeat feature enabled?
+ Vector2i m_previousSize; ///< Previous size of the window, to find if a ConfigureNotify event is a resize event (could be a move event only)
+ bool m_useSizeHints; ///< Is the size of the window fixed with size hints?
+ bool m_fullscreen; ///< Is the window in fullscreen?
+ bool m_cursorGrabbed; ///< Is the mouse cursor trapped?
+ bool m_windowMapped; ///< Has the window been mapped by the window manager?
+ Pixmap m_iconPixmap; ///< The current icon pixmap if in use
+ Pixmap m_iconMaskPixmap; ///< The current icon mask pixmap if in use
+ ::Time m_lastInputTime; ///< Last time we received user input
};
} // namespace priv
diff --git a/src/SFML/Window/Win32/WglContext.cpp b/src/SFML/Window/Win32/WglContext.cpp
index 486946f..a44c0c5 100644
--- a/src/SFML/Window/Win32/WglContext.cpp
+++ b/src/SFML/Window/Win32/WglContext.cpp
@@ -200,9 +200,9 @@ GlFunctionPointer WglContext::getFunction(const char* name)
////////////////////////////////////////////////////////////
-bool WglContext::makeCurrent()
+bool WglContext::makeCurrent(bool current)
{
- return m_deviceContext && m_context && wglMakeCurrent(m_deviceContext, m_context);
+ return m_deviceContext && m_context && wglMakeCurrent(current ? m_deviceContext : NULL, current ? m_context : NULL);
}
@@ -599,6 +599,18 @@ void WglContext::createContext(WglContext* shared)
attributes.push_back(0);
attributes.push_back(0);
+ if (sharedContext)
+ {
+ static Mutex mutex;
+ Lock lock(mutex);
+
+ if (!wglMakeCurrent(NULL, NULL))
+ {
+ err() << "Failed to deactivate shared context before sharing: " << getErrorString(GetLastError()).toAnsiString() << std::endl;
+ return;
+ }
+ }
+
// Create the context
m_context = wglCreateContextAttribsARB(m_deviceContext, sharedContext, &attributes[0]);
}
@@ -657,6 +669,12 @@ void WglContext::createContext(WglContext* shared)
static Mutex mutex;
Lock lock(mutex);
+ if (!wglMakeCurrent(NULL, NULL))
+ {
+ err() << "Failed to deactivate shared context before sharing: " << getErrorString(GetLastError()).toAnsiString() << std::endl;
+ return;
+ }
+
if (!wglShareLists(sharedContext, m_context))
err() << "Failed to share the OpenGL context: " << getErrorString(GetLastError()).toAnsiString() << std::endl;
}
diff --git a/src/SFML/Window/Win32/WglContext.hpp b/src/SFML/Window/Win32/WglContext.hpp
index ceecc2d..9017c93 100644
--- a/src/SFML/Window/Win32/WglContext.hpp
+++ b/src/SFML/Window/Win32/WglContext.hpp
@@ -93,10 +93,12 @@ public:
////////////////////////////////////////////////////////////
/// \brief Activate the context as the current target for rendering
///
+ /// \param current Whether to make the context current or no longer current
+ ///
/// \return True on success, false if any error happened
///
////////////////////////////////////////////////////////////
- virtual bool makeCurrent();
+ virtual bool makeCurrent(bool current);
////////////////////////////////////////////////////////////
/// \brief Display what has been rendered to the context so far
diff --git a/src/SFML/Window/iOS/EaglContext.hpp b/src/SFML/Window/iOS/EaglContext.hpp
index a3c48ea..2bcdc36 100644
--- a/src/SFML/Window/iOS/EaglContext.hpp
+++ b/src/SFML/Window/iOS/EaglContext.hpp
@@ -126,10 +126,12 @@ protected:
/// \brief Activate the context as the current target
/// for rendering
///
+ /// \param current Whether to make the context current or no longer current
+ ///
/// \return True on success, false if any error happened
///
////////////////////////////////////////////////////////////
- virtual bool makeCurrent();
+ virtual bool makeCurrent(bool current);
private:
diff --git a/src/SFML/Window/iOS/EaglContext.mm b/src/SFML/Window/iOS/EaglContext.mm
index e033718..37ab4c3 100644
--- a/src/SFML/Window/iOS/EaglContext.mm
+++ b/src/SFML/Window/iOS/EaglContext.mm
@@ -107,6 +107,9 @@ EaglContext::~EaglContext()
// Restore the previous context
[EAGLContext setCurrentContext:previousContext];
+
+ if (m_context == [EAGLContext currentContext])
+ [EAGLContext setCurrentContext:nil];
}
}
@@ -167,9 +170,12 @@ void EaglContext::recreateRenderBuffers(SFView* glView)
////////////////////////////////////////////////////////////
-bool EaglContext::makeCurrent()
+bool EaglContext::makeCurrent(bool current)
{
- return [EAGLContext setCurrentContext:m_context];
+ if (current)
+ return [EAGLContext setCurrentContext:m_context];
+
+ return [EAGLContext setCurrentContext:nil];
}
@@ -215,12 +221,18 @@ void EaglContext::createContext(EaglContext* shared,
// Create the context
if (shared)
+ {
+ [EAGLContext setCurrentContext:nil];
+
m_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1 sharegroup:[shared->m_context sharegroup]];
+ }
else
+ {
m_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
+ }
// Activate it
- makeCurrent();
+ makeCurrent(true);
// Create the framebuffer (this is the only allowed drawable on iOS)
glGenFramebuffersOES(1, &m_framebuffer);
@@ -230,6 +242,9 @@ void EaglContext::createContext(EaglContext* shared,
// Attach the context to the GL view for future updates
window->getGlView().context = this;
+
+ // Deactivate it
+ makeCurrent(false);
}
} // namespace priv
diff --git a/src/SFML/Window/iOS/SFAppDelegate.mm b/src/SFML/Window/iOS/SFAppDelegate.mm
index 3284b9a..09fa42e 100644
--- a/src/SFML/Window/iOS/SFAppDelegate.mm
+++ b/src/SFML/Window/iOS/SFAppDelegate.mm
@@ -214,8 +214,8 @@ namespace
// Send a Resized event to the current window
sf::Event event;
event.type = sf::Event::Resized;
- event.size.width = size.x * backingScaleFactor;
- event.size.height = size.y * backingScaleFactor;
+ event.size.width = size.x;
+ event.size.height = size.y;
sfWindow->forwardEvent(event);
}
}