summaryrefslogtreecommitdiff
path: root/src/SFML/Window/Unix
diff options
context:
space:
mode:
authorJames Cowgill <jcowgill@debian.org>2016-08-09 15:20:03 +0000
committerJames Cowgill <jcowgill@debian.org>2016-08-09 15:20:03 +0000
commitdf93e238e30e97850d76ad5585b8ab9ad9c03e67 (patch)
tree2ae5f3305e1ee1882f563d2803f94aa6446dc367 /src/SFML/Window/Unix
parent301fd78b3ac87cf1fbce9d2c955db89094a304a5 (diff)
Imported Upstream version 2.4.0+dfsg
Diffstat (limited to 'src/SFML/Window/Unix')
-rw-r--r--src/SFML/Window/Unix/Display.cpp2
-rw-r--r--src/SFML/Window/Unix/Display.hpp2
-rw-r--r--src/SFML/Window/Unix/GlxContext.cpp451
-rw-r--r--src/SFML/Window/Unix/GlxContext.hpp40
-rw-r--r--src/SFML/Window/Unix/GlxExtensions.cpp135
-rw-r--r--src/SFML/Window/Unix/GlxExtensions.hpp89
-rw-r--r--src/SFML/Window/Unix/GlxExtensions.txt9
-rw-r--r--src/SFML/Window/Unix/InputImpl.cpp2
-rw-r--r--src/SFML/Window/Unix/InputImpl.hpp2
-rw-r--r--src/SFML/Window/Unix/JoystickImpl.cpp38
-rw-r--r--src/SFML/Window/Unix/JoystickImpl.hpp8
-rw-r--r--src/SFML/Window/Unix/ScopedXcbPtr.hpp2
-rw-r--r--src/SFML/Window/Unix/ScopedXcbPtr.inl2
-rw-r--r--src/SFML/Window/Unix/SensorImpl.cpp2
-rw-r--r--src/SFML/Window/Unix/SensorImpl.hpp2
-rw-r--r--src/SFML/Window/Unix/VideoModeImpl.cpp2
-rw-r--r--src/SFML/Window/Unix/WindowImplX11.cpp224
-rw-r--r--src/SFML/Window/Unix/WindowImplX11.hpp16
18 files changed, 747 insertions, 281 deletions
diff --git a/src/SFML/Window/Unix/Display.cpp b/src/SFML/Window/Unix/Display.cpp
index c57ae0f..a078b97 100644
--- a/src/SFML/Window/Unix/Display.cpp
+++ b/src/SFML/Window/Unix/Display.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
+// 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.
diff --git a/src/SFML/Window/Unix/Display.hpp b/src/SFML/Window/Unix/Display.hpp
index 2b33c96..2743678 100644
--- a/src/SFML/Window/Unix/Display.hpp
+++ b/src/SFML/Window/Unix/Display.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
+// 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.
diff --git a/src/SFML/Window/Unix/GlxContext.cpp b/src/SFML/Window/Unix/GlxContext.cpp
index c89c9d3..7251db2 100644
--- a/src/SFML/Window/Unix/GlxContext.cpp
+++ b/src/SFML/Window/Unix/GlxContext.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
+// 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.
@@ -31,6 +31,7 @@
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
+#include <vector>
#if !defined(GLX_DEBUGGING) && defined(SFML_DEBUG)
// Enable this to print messages to err() everytime GLX produces errors
@@ -53,8 +54,8 @@ namespace
public:
GlxErrorHandler(::Display* display) :
- m_display(display),
- m_lock (glxErrorMutex)
+ m_lock (glxErrorMutex),
+ m_display(display)
{
glxErrorOccurred = false;
m_previousHandler = XSetErrorHandler(HandleXError);
@@ -95,101 +96,73 @@ void ensureExtensionsInit(::Display* display, int screen)
////////////////////////////////////////////////////////////
GlxContext::GlxContext(GlxContext* shared) :
+m_display (NULL),
m_window (0),
m_context (NULL),
-m_ownsWindow(true)
+m_pbuffer (0),
+m_ownsWindow(false)
{
- // Open a connection with the X server
- m_display = OpenDisplay();
- m_connection = XGetXCBConnection(m_display);
- xcb_screen_t* screen = XCBScreenOfDisplay(m_connection, DefaultScreen(m_display));
+ // Save the creation settings
+ m_settings = ContextSettings();
- // Choose the visual according to the context settings
- XVisualInfo visualInfo = selectBestVisual(m_display, VideoMode::getDesktopMode().bitsPerPixel, ContextSettings());
+ // Make sure that extensions are initialized if this is not the shared context
+ // The shared context is the context used to initialize the extensions
+ if (shared && shared->m_display)
+ ensureExtensionsInit(shared->m_display, DefaultScreen(shared->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,
- 1, 1,
- 0,
- XCB_WINDOW_CLASS_INPUT_OUTPUT,
- visualInfo.visualid,
- XCB_CW_COLORMAP,
- value_list
- );
+ // Create the rendering surface (window or pbuffer if supported)
+ createSurface(shared, 1, 1, VideoMode::getDesktopMode().bitsPerPixel);
// Create the context
- createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, ContextSettings());
+ createContext(shared);
}
////////////////////////////////////////////////////////////
GlxContext::GlxContext(GlxContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) :
+m_display (NULL),
m_window (0),
m_context (NULL),
+m_pbuffer (0),
m_ownsWindow(false)
{
- // Open a connection with the X server
- // (important: must be the same display as the owner window)
- m_display = OpenDisplay();
- m_connection = XGetXCBConnection(m_display);
+ // Save the creation settings
+ m_settings = settings;
- // Get the owner window and its device context
- m_window = static_cast< ::Window>(owner->getSystemHandle());
+ // Make sure that extensions are initialized if this is not the shared context
+ // The shared context is the context used to initialize the extensions
+ if (shared && shared->m_display)
+ ensureExtensionsInit(shared->m_display, DefaultScreen(shared->m_display));
+
+ // Create the rendering surface from the owner window
+ createSurface(static_cast< ::Window>(owner->getSystemHandle()));
// Create the context
- if (m_window)
- createContext(shared, bitsPerPixel, settings);
+ createContext(shared);
}
////////////////////////////////////////////////////////////
GlxContext::GlxContext(GlxContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height) :
+m_display (NULL),
m_window (0),
m_context (NULL),
-m_ownsWindow(true)
+m_pbuffer (0),
+m_ownsWindow(false)
{
- // Open a connection with the X server
- m_display = OpenDisplay();
- m_connection = XGetXCBConnection(m_display);
- xcb_screen_t* screen = XCBScreenOfDisplay(m_connection, DefaultScreen(m_display));
+ // Save the creation settings
+ m_settings = settings;
- // Choose the visual according to the context settings
- XVisualInfo visualInfo = selectBestVisual(m_display, VideoMode::getDesktopMode().bitsPerPixel, settings);
+ // Make sure that extensions are initialized if this is not the shared context
+ // The shared context is the context used to initialize the extensions
+ if (shared && shared->m_display)
+ ensureExtensionsInit(shared->m_display, DefaultScreen(shared->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 the hidden window
- 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
- );
+ // Create the rendering surface (window or pbuffer if supported)
+ createSurface(shared, width, height, VideoMode::getDesktopMode().bitsPerPixel);
// Create the context
- createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, settings);
+ createContext(shared);
}
@@ -213,6 +186,11 @@ GlxContext::~GlxContext()
#endif
}
+ if (m_pbuffer)
+ {
+ glXDestroyPbuffer(m_display, m_pbuffer);
+ }
+
// Destroy the window if we own it
if (m_window && m_ownsWindow)
{
@@ -242,7 +220,16 @@ bool GlxContext::makeCurrent()
GlxErrorHandler handler(m_display);
#endif
- bool result = glXMakeCurrent(m_display, m_window, m_context);
+ bool result = false;
+
+ 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);
+ }
#if defined(GLX_DEBUGGING)
if (glxErrorOccurred)
@@ -260,7 +247,9 @@ void GlxContext::display()
GlxErrorHandler handler(m_display);
#endif
- if (m_window)
+ if (m_pbuffer)
+ glXSwapBuffers(m_display, m_pbuffer);
+ else if (m_window)
glXSwapBuffers(m_display, m_window);
#if defined(GLX_DEBUGGING)
@@ -284,7 +273,7 @@ void GlxContext::setVerticalSyncEnabled(bool enabled)
// which would require us to link in an additional library
if (sfglx_ext_EXT_swap_control == sfglx_LOAD_SUCCEEDED)
{
- glXSwapIntervalEXT(m_display, glXGetCurrentDrawable(), enabled ? 1 : 0);
+ glXSwapIntervalEXT(m_display, m_pbuffer ? m_pbuffer : m_window, enabled ? 1 : 0);
}
else if (sfglx_ext_MESA_swap_control == sfglx_LOAD_SUCCEEDED)
{
@@ -321,7 +310,7 @@ XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPe
{
// Evaluate all the returned visuals, and pick the best one
int bestScore = 0x7FFFFFFF;
- XVisualInfo bestVisual;
+ XVisualInfo bestVisual = XVisualInfo();
for (int i = 0; i < count; ++i)
{
// Check mandatory attributes
@@ -331,7 +320,7 @@ XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPe
continue;
// Extract the components of the current visual
- int red, green, blue, alpha, depth, stencil, multiSampling, samples;
+ int red, green, blue, alpha, depth, stencil, multiSampling, samples, sRgb;
glXGetConfig(display, &visuals[i], GLX_RED_SIZE, &red);
glXGetConfig(display, &visuals[i], GLX_GREEN_SIZE, &green);
glXGetConfig(display, &visuals[i], GLX_BLUE_SIZE, &blue);
@@ -350,12 +339,21 @@ XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPe
samples = 0;
}
+ if ((sfglx_ext_EXT_framebuffer_sRGB == sfglx_LOAD_SUCCEEDED) || (sfglx_ext_ARB_framebuffer_sRGB == sfglx_LOAD_SUCCEEDED))
+ {
+ glXGetConfig(display, &visuals[i], GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, &sRgb);
+ }
+ else
+ {
+ sRgb = 0;
+ }
+
// TODO: Replace this with proper acceleration detection
bool accelerated = true;
// Evaluate the visual
int color = red + green + blue + alpha;
- int score = evaluateFormat(bitsPerPixel, settings, color, depth, stencil, multiSampling ? samples : 0, accelerated);
+ int score = evaluateFormat(bitsPerPixel, settings, color, depth, stencil, multiSampling ? samples : 0, accelerated, sRgb == True);
// If it's better than the current best, make it the new best
if (score < bestScore)
@@ -379,12 +377,45 @@ XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPe
}
}
+
////////////////////////////////////////////////////////////
-void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings)
+void GlxContext::updateSettingsFromVisualInfo(XVisualInfo* visualInfo)
{
- // Save the creation settings
- m_settings = settings;
+ // Update the creation settings from the chosen format
+ int depth, stencil, multiSampling, samples, sRgb;
+ glXGetConfig(m_display, visualInfo, GLX_DEPTH_SIZE, &depth);
+ glXGetConfig(m_display, visualInfo, GLX_STENCIL_SIZE, &stencil);
+
+ if (sfglx_ext_ARB_multisample == sfglx_LOAD_SUCCEEDED)
+ {
+ glXGetConfig(m_display, visualInfo, GLX_SAMPLE_BUFFERS_ARB, &multiSampling);
+ glXGetConfig(m_display, visualInfo, GLX_SAMPLES_ARB, &samples);
+ }
+ else
+ {
+ multiSampling = 0;
+ samples = 0;
+ }
+ if ((sfglx_ext_EXT_framebuffer_sRGB == sfglx_LOAD_SUCCEEDED) || (sfglx_ext_ARB_framebuffer_sRGB == sfglx_LOAD_SUCCEEDED))
+ {
+ glXGetConfig(m_display, visualInfo, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, &sRgb);
+ }
+ else
+ {
+ sRgb = 0;
+ }
+
+ m_settings.depthBits = static_cast<unsigned int>(depth);
+ m_settings.stencilBits = static_cast<unsigned int>(stencil);
+ m_settings.antialiasingLevel = multiSampling ? samples : 0;
+ m_settings.sRgbCapable = (sRgb == True);
+}
+
+
+////////////////////////////////////////////////////////////
+void GlxContext::updateSettingsFromWindow()
+{
// Retrieve the attributes of the target window
XWindowAttributes windowAttributes;
if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0)
@@ -400,6 +431,180 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co
int nbVisuals = 0;
XVisualInfo* visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals);
+ if (!visualInfo)
+ return;
+
+ updateSettingsFromVisualInfo(visualInfo);
+
+ XFree(visualInfo);
+}
+
+
+////////////////////////////////////////////////////////////
+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);
+
+ // Check if the shared context already exists and pbuffers are supported
+ if (shared && (sfglx_ext_SGIX_pbuffer == sfglx_LOAD_SUCCEEDED))
+ {
+ // There are no GLX versions prior to 1.0
+ int major = 0;
+ int minor = 0;
+
+ glXQueryVersion(m_display, &major, &minor);
+
+ // Check if glXCreatePbuffer is available (requires GLX 1.3 or greater)
+ bool hasCreatePbuffer = ((major > 1) || (minor >= 3));
+
+ if (hasCreatePbuffer)
+ {
+ // Get a GLXFBConfig that matches the visual
+ GLXFBConfig* config = NULL;
+
+ // We don't supply attributes to match against, since
+ // the visual we are matching against was already
+ // deemed suitable in selectBestVisual()
+ int nbConfigs = 0;
+ GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), NULL, &nbConfigs);
+
+ for (int i = 0; configs && (i < nbConfigs); ++i)
+ {
+ XVisualInfo* visual = glXGetVisualFromFBConfig(m_display, configs[i]);
+
+ if (!visual)
+ continue;
+
+ if (visual->visualid == visualInfo.visualid)
+ {
+ config = &configs[i];
+ break;
+ }
+ }
+
+ if (config)
+ {
+ int attributes[] =
+ {
+ GLX_PBUFFER_WIDTH, static_cast<int>(width),
+ GLX_PBUFFER_HEIGHT, static_cast<int>(height),
+ 0, 0
+ };
+
+ m_pbuffer = glXCreatePbuffer(m_display, *config, attributes);
+
+ updateSettingsFromVisualInfo(&visualInfo);
+
+ XFree(configs);
+
+ return;
+ }
+
+ if (configs)
+ XFree(configs);
+ }
+ }
+
+ // 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));
+
+ // 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
+ );
+
+ m_ownsWindow = true;
+
+ updateSettingsFromWindow();
+}
+
+
+////////////////////////////////////////////////////////////
+void GlxContext::createSurface(::Window window)
+{
+ m_display = OpenDisplay();
+ m_connection = XGetXCBConnection(m_display);
+
+ // A window already exists, so just use it
+ m_window = window;
+
+ updateSettingsFromWindow();
+}
+
+
+////////////////////////////////////////////////////////////
+void GlxContext::createContext(GlxContext* shared)
+{
+ // Get a working copy of the context settings
+ ContextSettings settings = m_settings;
+
+ XVisualInfo* visualInfo = NULL;
+
+ if (m_pbuffer)
+ {
+ unsigned int fbConfigId = 0;
+
+ glXQueryDrawable(m_display, m_pbuffer, GLX_FBCONFIG_ID, &fbConfigId);
+
+ int attributes[] =
+ {
+ GLX_FBCONFIG_ID, static_cast<int>(fbConfigId),
+ 0, 0
+ };
+
+ int count = 0;
+ GLXFBConfig* fbconfig = glXChooseFBConfig(m_display, DefaultScreen(m_display), attributes, &count);
+
+ if (count == 1)
+ visualInfo = glXGetVisualFromFBConfig(m_display, *fbconfig);
+
+ if (fbconfig)
+ XFree(fbconfig);
+ }
+ else
+ {
+ // Retrieve the attributes of the target window
+ XWindowAttributes windowAttributes;
+ if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0)
+ {
+ err() << "Failed to get the window attributes" << std::endl;
+ return;
+ }
+
+ // Get its visuals
+ XVisualInfo tpl;
+ tpl.screen = DefaultScreen(m_display);
+ tpl.visualid = XVisualIDFromVisual(windowAttributes.visual);
+ int nbVisuals = 0;
+ visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals);
+ }
+
+ if (!visualInfo)
+ {
+ err() << "Failed to get visual info" << std::endl;
+ return;
+ }
+
// Get the context to share display lists with
GLXContext toShare = shared ? shared->m_context : NULL;
@@ -410,26 +615,13 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co
if (!glXQueryVersion(m_display, &major, &minor))
err() << "Failed to query GLX version, limited to legacy context creation" << std::endl;
- // Make sure that extensions are initialized if this is not the shared context
- // The shared context is the context used to initialize the extensions
- if (shared)
- ensureExtensionsInit(m_display, DefaultScreen(m_display));
-
// Check if glXCreateContextAttribsARB is available (requires GLX 1.3 or greater)
bool hasCreateContextArb = (sfglx_ext_ARB_create_context == sfglx_LOAD_SUCCEEDED) && ((major > 1) || (minor >= 3));
- // Check if we need to use glXCreateContextAttribsARB
- bool needCreateContextArb = false;
-
- if (m_settings.attributeFlags)
- needCreateContextArb = true;
- else if (m_settings.majorVersion >= 3)
- needCreateContextArb = true;
-
- // Create the OpenGL context -- first try using glXCreateContextAttribsARB if we need to
- if (hasCreateContextArb && needCreateContextArb)
+ // Create the OpenGL context -- first try using glXCreateContextAttribsARB
+ if (hasCreateContextArb)
{
- // Get a GLXFBConfig that matches the the window's visual, for glXCreateContextAttribsARB
+ // Get a GLXFBConfig that matches the window's visual, for glXCreateContextAttribsARB
GLXFBConfig* config = NULL;
// We don't supply attributes to match against, since
@@ -457,27 +649,27 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co
while (config && !m_context && m_settings.majorVersion)
{
+ std::vector<int> attributes;
+
+ // Check if the user requested a specific context version (anything > 1.1)
+ if ((m_settings.majorVersion > 1) || ((m_settings.majorVersion == 1) && (m_settings.minorVersion > 1)))
+ {
+ attributes.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB);
+ attributes.push_back(m_settings.majorVersion);
+ attributes.push_back(GLX_CONTEXT_MINOR_VERSION_ARB);
+ attributes.push_back(m_settings.minorVersion);
+ }
+
// Check if setting the profile is supported
if (sfglx_ext_ARB_create_context_profile == sfglx_LOAD_SUCCEEDED)
{
int profile = (m_settings.attributeFlags & ContextSettings::Core) ? GLX_CONTEXT_CORE_PROFILE_BIT_ARB : GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
int debug = (m_settings.attributeFlags & ContextSettings::Debug) ? GLX_CONTEXT_DEBUG_BIT_ARB : 0;
- // Create the context
- int attributes[] =
- {
- GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast<int>(m_settings.majorVersion),
- GLX_CONTEXT_MINOR_VERSION_ARB, static_cast<int>(m_settings.minorVersion),
- GLX_CONTEXT_PROFILE_MASK_ARB, profile,
- GLX_CONTEXT_FLAGS_ARB, debug,
- 0, 0
- };
-
- // RAII GLX error handler (we simply ignore errors here)
- // On an error, glXCreateContextAttribsARB will return 0 anyway
- GlxErrorHandler handler(m_display);
-
- m_context = glXCreateContextAttribsARB(m_display, *config, toShare, true, attributes);
+ attributes.push_back(GLX_CONTEXT_PROFILE_MASK_ARB);
+ attributes.push_back(profile);
+ attributes.push_back(GLX_CONTEXT_FLAGS_ARB);
+ attributes.push_back(debug);
}
else
{
@@ -486,21 +678,18 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co
<< "disabling comptibility and debug" << std::endl;
m_settings.attributeFlags = ContextSettings::Default;
+ }
- // Create the context
- int attributes[] =
- {
- GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast<int>(m_settings.majorVersion),
- GLX_CONTEXT_MINOR_VERSION_ARB, static_cast<int>(m_settings.minorVersion),
- 0, 0
- };
+ // Append the terminating 0
+ attributes.push_back(0);
+ attributes.push_back(0);
- // RAII GLX error handler (we simply ignore errors here)
- // On an error, glXCreateContextAttribsARB will return 0 anyway
- GlxErrorHandler handler(m_display);
+ // RAII GLX error handler (we simply ignore errors here)
+ // On an error, glXCreateContextAttribsARB will return 0 anyway
+ GlxErrorHandler handler(m_display);
- m_context = glXCreateContextAttribsARB(m_display, *config, toShare, true, attributes);
- }
+ // Create the context
+ m_context = glXCreateContextAttribsARB(m_display, *config, toShare, true, &attributes[0]);
if (!m_context)
{
@@ -555,31 +744,7 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co
}
if (!m_context)
- {
err() << "Failed to create an OpenGL context for this window" << std::endl;
- }
- else
- {
- // Update the creation settings from the chosen format
- int depth, stencil, multiSampling, samples;
- glXGetConfig(m_display, visualInfo, GLX_DEPTH_SIZE, &depth);
- glXGetConfig(m_display, visualInfo, GLX_STENCIL_SIZE, &stencil);
-
- if (sfglx_ext_ARB_multisample == sfglx_LOAD_SUCCEEDED)
- {
- glXGetConfig(m_display, visualInfo, GLX_SAMPLE_BUFFERS_ARB, &multiSampling);
- glXGetConfig(m_display, visualInfo, GLX_SAMPLES_ARB, &samples);
- }
- else
- {
- multiSampling = 0;
- samples = 0;
- }
-
- m_settings.depthBits = static_cast<unsigned int>(depth);
- m_settings.stencilBits = static_cast<unsigned int>(stencil);
- m_settings.antialiasingLevel = multiSampling ? samples : 0;
- }
// Free the visual info
XFree(visualInfo);
diff --git a/src/SFML/Window/Unix/GlxContext.hpp b/src/SFML/Window/Unix/GlxContext.hpp
index e1ad899..4a9444f 100644
--- a/src/SFML/Window/Unix/GlxContext.hpp
+++ b/src/SFML/Window/Unix/GlxContext.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
+// 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.
@@ -133,14 +133,45 @@ public:
private:
////////////////////////////////////////////////////////////
- /// \brief Create the context
+ /// \brief Update the context visual settings from XVisualInfo
+ ///
+ /// \param visualInfo XVisualInfo to update settings from
+ ///
+ ////////////////////////////////////////////////////////////
+ void updateSettingsFromVisualInfo(XVisualInfo* visualInfo);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Update the context visual settings from the window
+ ///
+ ////////////////////////////////////////////////////////////
+ void updateSettingsFromWindow();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create the context's drawing surface
///
/// \param shared Context to share the new one with (can be NULL)
+ /// \param width Back buffer width, in pixels
+ /// \param height Back buffer height, in pixels
/// \param bitsPerPixel Pixel depth, in bits per pixel
- /// \param settings Creation parameters
///
////////////////////////////////////////////////////////////
- void createContext(GlxContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings);
+ void createSurface(GlxContext* shared, unsigned int width, unsigned int height, unsigned int bitsPerPixel);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create the context's drawing surface from an existing window
+ ///
+ /// \param window Window ID of the owning window
+ ///
+ ////////////////////////////////////////////////////////////
+ void createSurface(::Window window);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Create the context
+ ///
+ /// \param shared Context to share the new one with (can be NULL)
+ ///
+ ////////////////////////////////////////////////////////////
+ void createContext(GlxContext* shared);
////////////////////////////////////////////////////////////
// Member data
@@ -149,6 +180,7 @@ private:
::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/GlxExtensions.cpp b/src/SFML/Window/Unix/GlxExtensions.cpp
index 029095c..e418e2e 100644
--- a/src/SFML/Window/Unix/GlxExtensions.cpp
+++ b/src/SFML/Window/Unix/GlxExtensions.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
+// 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.
@@ -30,6 +30,7 @@
#include <cstdlib>
#include <cstring>
#include <cstddef>
+#include <string>
static sf::GlFunctionPointer IntGetProcAddress(const char* name)
{
@@ -39,17 +40,21 @@ static sf::GlFunctionPointer IntGetProcAddress(const char* name)
int sfglx_ext_EXT_swap_control = sfglx_LOAD_FAILED;
int sfglx_ext_MESA_swap_control = sfglx_LOAD_FAILED;
int sfglx_ext_SGI_swap_control = sfglx_LOAD_FAILED;
+int sfglx_ext_EXT_framebuffer_sRGB = sfglx_LOAD_FAILED;
+int sfglx_ext_ARB_framebuffer_sRGB = sfglx_LOAD_FAILED;
int sfglx_ext_ARB_multisample = sfglx_LOAD_FAILED;
+int sfglx_ext_SGIX_pbuffer = sfglx_LOAD_FAILED;
int sfglx_ext_ARB_create_context = sfglx_LOAD_FAILED;
int sfglx_ext_ARB_create_context_profile = sfglx_LOAD_FAILED;
-void (CODEGEN_FUNCPTR *sf_ptrc_glXSwapIntervalEXT)(Display *, GLXDrawable, int) = NULL;
+void (CODEGEN_FUNCPTR *sf_ptrc_glXSwapIntervalEXT)(Display*, GLXDrawable, int) = NULL;
static int Load_EXT_swap_control(void)
{
int numFailed = 0;
- sf_ptrc_glXSwapIntervalEXT = (void (CODEGEN_FUNCPTR *)(Display *, GLXDrawable, int))IntGetProcAddress("glXSwapIntervalEXT");
- if(!sf_ptrc_glXSwapIntervalEXT) numFailed++;
+ sf_ptrc_glXSwapIntervalEXT = reinterpret_cast<void (CODEGEN_FUNCPTR*)(Display*, GLXDrawable, int)>(IntGetProcAddress("glXSwapIntervalEXT"));
+ if (!sf_ptrc_glXSwapIntervalEXT)
+ numFailed++;
return numFailed;
}
@@ -58,8 +63,9 @@ int (CODEGEN_FUNCPTR *sf_ptrc_glXSwapIntervalMESA)(int) = NULL;
static int Load_MESA_swap_control(void)
{
int numFailed = 0;
- sf_ptrc_glXSwapIntervalMESA = (int (CODEGEN_FUNCPTR *)(int))IntGetProcAddress("glXSwapIntervalMESA");
- if(!sf_ptrc_glXSwapIntervalMESA) numFailed++;
+ sf_ptrc_glXSwapIntervalMESA = reinterpret_cast<int (CODEGEN_FUNCPTR*)(int)>(IntGetProcAddress("glXSwapIntervalMESA"));
+ if (!sf_ptrc_glXSwapIntervalMESA)
+ numFailed++;
return numFailed;
}
@@ -68,74 +74,110 @@ int (CODEGEN_FUNCPTR *sf_ptrc_glXSwapIntervalSGI)(int) = NULL;
static int Load_SGI_swap_control(void)
{
int numFailed = 0;
- sf_ptrc_glXSwapIntervalSGI = (int (CODEGEN_FUNCPTR *)(int))IntGetProcAddress("glXSwapIntervalSGI");
- if(!sf_ptrc_glXSwapIntervalSGI) numFailed++;
+ sf_ptrc_glXSwapIntervalSGI = reinterpret_cast<int (CODEGEN_FUNCPTR *)(int)>(IntGetProcAddress("glXSwapIntervalSGI"));
+ if (!sf_ptrc_glXSwapIntervalSGI)
+ numFailed++;
return numFailed;
}
-GLXContext (CODEGEN_FUNCPTR *sf_ptrc_glXCreateContextAttribsARB)(Display *, GLXFBConfig, GLXContext, Bool, const int *) = NULL;
+GLXPbufferSGIX (CODEGEN_FUNCPTR *sf_ptrc_glXCreateGLXPbufferSGIX)(Display*, GLXFBConfigSGIX, unsigned int, unsigned int, int*) = NULL;
+void (CODEGEN_FUNCPTR *sf_ptrc_glXDestroyGLXPbufferSGIX)(Display*, GLXPbufferSGIX) = NULL;
+void (CODEGEN_FUNCPTR *sf_ptrc_glXGetSelectedEventSGIX)(Display*, GLXDrawable, unsigned long*) = NULL;
+int (CODEGEN_FUNCPTR *sf_ptrc_glXQueryGLXPbufferSGIX)(Display*, GLXPbufferSGIX, int, unsigned int*) = NULL;
+void (CODEGEN_FUNCPTR *sf_ptrc_glXSelectEventSGIX)(Display*, GLXDrawable, unsigned long) = NULL;
+
+static int Load_SGIX_pbuffer(void)
+{
+ int numFailed = 0;
+ sf_ptrc_glXCreateGLXPbufferSGIX = reinterpret_cast<GLXPbufferSGIX (CODEGEN_FUNCPTR*)(Display*, GLXFBConfigSGIX, unsigned int, unsigned int, int*)>(IntGetProcAddress("glXCreateGLXPbufferSGIX"));
+ if (!sf_ptrc_glXCreateGLXPbufferSGIX)
+ numFailed++;
+ sf_ptrc_glXDestroyGLXPbufferSGIX = reinterpret_cast<void (CODEGEN_FUNCPTR*)(Display*, GLXPbufferSGIX)>(IntGetProcAddress("glXDestroyGLXPbufferSGIX"));
+ if (!sf_ptrc_glXDestroyGLXPbufferSGIX)
+ numFailed++;
+ sf_ptrc_glXGetSelectedEventSGIX = reinterpret_cast<void (CODEGEN_FUNCPTR*)(Display*, GLXDrawable, unsigned long*)>(IntGetProcAddress("glXGetSelectedEventSGIX"));
+ if (!sf_ptrc_glXGetSelectedEventSGIX)
+ numFailed++;
+ sf_ptrc_glXQueryGLXPbufferSGIX = reinterpret_cast<int (CODEGEN_FUNCPTR*)(Display*, GLXPbufferSGIX, int, unsigned int*)>(IntGetProcAddress("glXQueryGLXPbufferSGIX"));
+ if (!sf_ptrc_glXQueryGLXPbufferSGIX)
+ numFailed++;
+ sf_ptrc_glXSelectEventSGIX = reinterpret_cast<void (CODEGEN_FUNCPTR*)(Display*, GLXDrawable, unsigned long)>(IntGetProcAddress("glXSelectEventSGIX"));
+ if (!sf_ptrc_glXSelectEventSGIX)
+ numFailed++;
+ return numFailed;
+}
+
+GLXContext (CODEGEN_FUNCPTR *sf_ptrc_glXCreateContextAttribsARB)(Display*, GLXFBConfig, GLXContext, Bool, const int*) = NULL;
static int Load_ARB_create_context(void)
{
int numFailed = 0;
- sf_ptrc_glXCreateContextAttribsARB = (GLXContext (CODEGEN_FUNCPTR *)(Display *, GLXFBConfig, GLXContext, Bool, const int *))IntGetProcAddress("glXCreateContextAttribsARB");
- if(!sf_ptrc_glXCreateContextAttribsARB) numFailed++;
+ sf_ptrc_glXCreateContextAttribsARB = reinterpret_cast<GLXContext (CODEGEN_FUNCPTR*)(Display*, GLXFBConfig, GLXContext, Bool, const int*)>(IntGetProcAddress("glXCreateContextAttribsARB"));
+ if (!sf_ptrc_glXCreateContextAttribsARB)
+ numFailed++;
return numFailed;
}
typedef int (*PFN_LOADFUNCPOINTERS)(void);
typedef struct sfglx_StrToExtMap_s
{
- const char *extensionName;
- int *extensionVariable;
+ const char* extensionName;
+ int* extensionVariable;
PFN_LOADFUNCPOINTERS LoadExtension;
} sfglx_StrToExtMap;
-static sfglx_StrToExtMap ExtensionMap[6] = {
+static sfglx_StrToExtMap ExtensionMap[9] = {
{"GLX_EXT_swap_control", &sfglx_ext_EXT_swap_control, Load_EXT_swap_control},
{"GLX_MESA_swap_control", &sfglx_ext_MESA_swap_control, Load_MESA_swap_control},
{"GLX_SGI_swap_control", &sfglx_ext_SGI_swap_control, Load_SGI_swap_control},
+ {"GLX_EXT_framebuffer_sRGB", &sfglx_ext_EXT_framebuffer_sRGB, NULL},
+ {"GLX_ARB_framebuffer_sRGB", &sfglx_ext_ARB_framebuffer_sRGB, NULL},
{"GLX_ARB_multisample", &sfglx_ext_ARB_multisample, NULL},
+ {"GLX_SGIX_pbuffer", &sfglx_ext_SGIX_pbuffer, Load_SGIX_pbuffer},
{"GLX_ARB_create_context", &sfglx_ext_ARB_create_context, Load_ARB_create_context},
- {"GLX_ARB_create_context_profile", &sfglx_ext_ARB_create_context_profile, NULL},
+ {"GLX_ARB_create_context_profile", &sfglx_ext_ARB_create_context_profile, NULL}
};
-static int g_extensionMapSize = 6;
+static int g_extensionMapSize = 9;
+
-static sfglx_StrToExtMap *FindExtEntry(const char *extensionName)
+static sfglx_StrToExtMap* FindExtEntry(const char* extensionName)
{
- int loop;
- sfglx_StrToExtMap *currLoc = ExtensionMap;
- for(loop = 0; loop < g_extensionMapSize; ++loop, ++currLoc)
+ sfglx_StrToExtMap* currLoc = ExtensionMap;
+ for (int loop = 0; loop < g_extensionMapSize; ++loop, ++currLoc)
{
- if(strcmp(extensionName, currLoc->extensionName) == 0)
+ if (std::strcmp(extensionName, currLoc->extensionName) == 0)
return currLoc;
}
return NULL;
}
+
static void ClearExtensionVars(void)
{
sfglx_ext_EXT_swap_control = sfglx_LOAD_FAILED;
sfglx_ext_MESA_swap_control = sfglx_LOAD_FAILED;
sfglx_ext_SGI_swap_control = sfglx_LOAD_FAILED;
+ sfglx_ext_EXT_framebuffer_sRGB = sfglx_LOAD_FAILED;
+ sfglx_ext_ARB_framebuffer_sRGB = sfglx_LOAD_FAILED;
sfglx_ext_ARB_multisample = sfglx_LOAD_FAILED;
+ sfglx_ext_SGIX_pbuffer = sfglx_LOAD_FAILED;
sfglx_ext_ARB_create_context = sfglx_LOAD_FAILED;
sfglx_ext_ARB_create_context_profile = sfglx_LOAD_FAILED;
}
-static void LoadExtByName(const char *extensionName)
+static void LoadExtByName(const char* extensionName)
{
- sfglx_StrToExtMap *entry = NULL;
+ sfglx_StrToExtMap* entry = NULL;
entry = FindExtEntry(extensionName);
- if(entry)
+ if (entry)
{
- if(entry->LoadExtension)
+ if (entry->LoadExtension)
{
int numFailed = entry->LoadExtension();
- if(numFailed == 0)
+ if (numFailed == 0)
{
*(entry->extensionVariable) = sfglx_LOAD_SUCCEEDED;
}
@@ -152,46 +194,25 @@ static void LoadExtByName(const char *extensionName)
}
-static void ProcExtsFromExtString(const char *strExtList)
+static void ProcExtsFromExtString(const char* strExtList)
{
- size_t iExtListLen = strlen(strExtList);
- const char *strExtListEnd = strExtList + iExtListLen;
- const char *strCurrPos = strExtList;
- char strWorkBuff[256];
-
- while(*strCurrPos)
+ do
{
- /*Get the extension at our position.*/
- int iStrLen = 0;
- const char *strEndStr = strchr(strCurrPos, ' ');
- int iStop = 0;
- if(strEndStr == NULL)
- {
- strEndStr = strExtListEnd;
- iStop = 1;
- }
-
- iStrLen = (int)((ptrdiff_t)strEndStr - (ptrdiff_t)strCurrPos);
-
- if(iStrLen > 255)
- return;
+ const char* begin = strExtList;
- strncpy(strWorkBuff, strCurrPos, iStrLen);
- strWorkBuff[iStrLen] = '\0';
+ while ((*strExtList != ' ') && *strExtList)
+ strExtList++;
- LoadExtByName(strWorkBuff);
-
- strCurrPos = strEndStr + 1;
- if(iStop) break;
- }
+ LoadExtByName(std::string(begin, strExtList).c_str());
+ } while (*strExtList++);
}
-int sfglx_LoadFunctions(Display *display, int screen)
+
+int sfglx_LoadFunctions(Display* display, int screen)
{
ClearExtensionVars();
- ProcExtsFromExtString((const char *)glXQueryExtensionsString(display, screen));
+ ProcExtsFromExtString(reinterpret_cast<const char*>(glXQueryExtensionsString(display, screen)));
return sfglx_LOAD_SUCCEEDED;
}
-
diff --git a/src/SFML/Window/Unix/GlxExtensions.hpp b/src/SFML/Window/Unix/GlxExtensions.hpp
index 9e9a749..44c9165 100644
--- a/src/SFML/Window/Unix/GlxExtensions.hpp
+++ b/src/SFML/Window/Unix/GlxExtensions.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
+// 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.
@@ -36,7 +36,7 @@
#include <GL/glx.h>
#ifdef CODEGEN_FUNCPTR
#undef CODEGEN_FUNCPTR
-#endif /*CODEGEN_FUNCPTR*/
+#endif // CODEGEN_FUNCPTR
#define CODEGEN_FUNCPTR
#ifndef GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS
@@ -58,21 +58,21 @@ typedef double GLdouble;
typedef double GLclampd;
#define GLvoid void
-#endif /*GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS*/
+#endif // GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS
#ifndef GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS
#define GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS
-#endif /*GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS*/
+#endif // GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS
#ifndef GLEXT_64_TYPES_DEFINED
-/* This code block is duplicated in glext.h, so must be protected */
+// This code block is duplicated in glext.h, so must be protected
#define GLEXT_64_TYPES_DEFINED
-/* Define int32_t, int64_t, and uint64_t types for UST/MSC */
-/* (as used in the GLX_OML_sync_control extension). */
+// Define int32_t, int64_t, and uint64_t types for UST/MSC
+// (as used in the GLX_OML_sync_control extension).
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#include <inttypes.h>
#elif defined(__sun__) || defined(__digital__)
@@ -84,8 +84,8 @@ typedef unsigned long int uint64_t;
#else
typedef long long int int64_t;
typedef unsigned long long int uint64_t;
-#endif /* __arch64__ */
-#endif /* __STDC__ */
+#endif // __arch64__
+#endif // __STDC__
#elif defined( __VMS ) || defined(__sgi)
#include <inttypes.h>
#elif defined(__SCO__) || defined(__USLC__)
@@ -101,7 +101,7 @@ typedef __int32 int32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
-/* Fallback if nothing above works */
+// Fallback if nothing above works
#include <inttypes.h>
#endif
#endif
@@ -118,42 +118,75 @@ typedef unsigned __int64 uint64_t;
typedef struct __GLXFBConfigRec *GLXFBConfigSGIX;
typedef XID GLXPbufferSGIX;
typedef struct {
- char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
+ char pipeName[80]; // Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]
int networkId;
} GLXHyperpipeNetworkSGIX;
typedef struct {
- char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
+ char pipeName[80]; // Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]
int channel;
unsigned int participationType;
int timeSlice;
} GLXHyperpipeConfigSGIX;
typedef struct {
- char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
+ char pipeName[80]; // Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]
int srcXOrigin, srcYOrigin, srcWidth, srcHeight;
int destXOrigin, destYOrigin, destWidth, destHeight;
} GLXPipeRect;
typedef struct {
- char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
+ char pipeName[80]; // Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]
int XOrigin, YOrigin, maxHeight, maxWidth;
} GLXPipeRectLimits;
#ifdef __cplusplus
extern "C" {
-#endif /*__cplusplus*/
+#endif // __cplusplus
extern int sfglx_ext_EXT_swap_control;
extern int sfglx_ext_MESA_swap_control;
extern int sfglx_ext_SGI_swap_control;
+extern int sfglx_ext_EXT_framebuffer_sRGB;
+extern int sfglx_ext_ARB_framebuffer_sRGB;
extern int sfglx_ext_ARB_multisample;
+extern int sfglx_ext_SGIX_pbuffer;
extern int sfglx_ext_ARB_create_context;
extern int sfglx_ext_ARB_create_context_profile;
#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
#define GLX_SWAP_INTERVAL_EXT 0x20F1
+#define GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20B2
+
+#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2
+
#define GLX_SAMPLES_ARB 100001
#define GLX_SAMPLE_BUFFERS_ARB 100000
+#define GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080
+#define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010
+#define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004
+#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008
+#define GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000
+#define GLX_DAMAGED_SGIX 0x8020
+#define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020
+#define GLX_EVENT_MASK_SGIX 0x801F
+#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001
+#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002
+#define GLX_HEIGHT_SGIX 0x801E
+#define GLX_LARGEST_PBUFFER_SGIX 0x801C
+#define GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017
+#define GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018
+#define GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016
+#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A
+#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019
+#define GLX_PBUFFER_BIT_SGIX 0x00000004
+#define GLX_PBUFFER_SGIX 0x8023
+#define GLX_PRESERVED_CONTENTS_SGIX 0x801B
+#define GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100
+#define GLX_SAVED_SGIX 0x8021
+#define GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040
+#define GLX_WIDTH_SGIX 0x801D
+#define GLX_WINDOW_SGIX 0x8022
+
#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
#define GLX_CONTEXT_FLAGS_ARB 0x2094
#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
@@ -168,7 +201,7 @@ extern int sfglx_ext_ARB_create_context_profile;
#define GLX_EXT_swap_control 1
extern void (CODEGEN_FUNCPTR *sf_ptrc_glXSwapIntervalEXT)(Display *, GLXDrawable, int);
#define glXSwapIntervalEXT sf_ptrc_glXSwapIntervalEXT
-#endif /*GLX_EXT_swap_control*/
+#endif // GLX_EXT_swap_control
// Declare entry point even if GLX header already provides glXSwapIntervalMESA
// We won't make use of an alias here
@@ -178,13 +211,27 @@ extern int (CODEGEN_FUNCPTR *sf_ptrc_glXSwapIntervalMESA)(int);
#define GLX_SGI_swap_control 1
extern int (CODEGEN_FUNCPTR *sf_ptrc_glXSwapIntervalSGI)(int);
#define glXSwapIntervalSGI sf_ptrc_glXSwapIntervalSGI
-#endif /*GLX_SGI_swap_control*/
+#endif // GLX_SGI_swap_control
+
+#ifndef GLX_SGIX_pbuffer
+#define GLX_SGIX_pbuffer 1
+extern GLXPbufferSGIX (CODEGEN_FUNCPTR *sf_ptrc_glXCreateGLXPbufferSGIX)(Display*, GLXFBConfigSGIX, unsigned int, unsigned int, int*);
+#define glXCreateGLXPbufferSGIX sf_ptrc_glXCreateGLXPbufferSGIX
+extern void (CODEGEN_FUNCPTR *sf_ptrc_glXDestroyGLXPbufferSGIX)(Display*, GLXPbufferSGIX);
+#define glXDestroyGLXPbufferSGIX sf_ptrc_glXDestroyGLXPbufferSGIX
+extern void (CODEGEN_FUNCPTR *sf_ptrc_glXGetSelectedEventSGIX)(Display*, GLXDrawable, unsigned long*);
+#define glXGetSelectedEventSGIX sf_ptrc_glXGetSelectedEventSGIX
+extern int (CODEGEN_FUNCPTR *sf_ptrc_glXQueryGLXPbufferSGIX)(Display*, GLXPbufferSGIX, int, unsigned int*);
+#define glXQueryGLXPbufferSGIX sf_ptrc_glXQueryGLXPbufferSGIX
+extern void (CODEGEN_FUNCPTR *sf_ptrc_glXSelectEventSGIX)(Display*, GLXDrawable, unsigned long);
+#define glXSelectEventSGIX sf_ptrc_glXSelectEventSGIX
+#endif // GLX_SGIX_pbuffer
#ifndef GLX_ARB_create_context
#define GLX_ARB_create_context 1
-extern GLXContext (CODEGEN_FUNCPTR *sf_ptrc_glXCreateContextAttribsARB)(Display *, GLXFBConfig, GLXContext, Bool, const int *);
+extern GLXContext (CODEGEN_FUNCPTR *sf_ptrc_glXCreateContextAttribsARB)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
#define glXCreateContextAttribsARB sf_ptrc_glXCreateContextAttribsARB
-#endif /*GLX_ARB_create_context*/
+#endif // GLX_ARB_create_context
enum sfglx_LoadStatus
@@ -198,6 +245,6 @@ int sfglx_LoadFunctions(Display *display, int screen);
#ifdef __cplusplus
}
-#endif /*__cplusplus*/
+#endif // __cplusplus
-#endif /* SF_POINTER_C_GENERATED_HEADER_GLXWIN_HPP */
+#endif // SF_POINTER_C_GENERATED_HEADER_GLXWIN_HPP
diff --git a/src/SFML/Window/Unix/GlxExtensions.txt b/src/SFML/Window/Unix/GlxExtensions.txt
index b6b06fa..9c8a641 100644
--- a/src/SFML/Window/Unix/GlxExtensions.txt
+++ b/src/SFML/Window/Unix/GlxExtensions.txt
@@ -1,11 +1,14 @@
// Created with:
-// https://bitbucket.org/Anteru/glloadgen-reloaded
-// Commit 20f19482b7a844d20b9785c3e3fd1f16419f6e0a
+// https://bitbucket.org/KhronosGroup/glloadgen
+// Commit d143d66ac90d538ed06f806188714861b8e8e2f9
// lua LoadGen.lua -style=pointer_c -spec=glX -indent=space -prefix=sf -extfile=GlxExtensions.txt GlxExtensions
EXT_swap_control
// MESA_swap_control
SGI_swap_control
+EXT_framebuffer_sRGB
+ARB_framebuffer_sRGB
GLX_ARB_multisample
+GLX_SGIX_pbuffer
GLX_ARB_create_context
-GLX_ARB_create_context_profile \ No newline at end of file
+GLX_ARB_create_context_profile
diff --git a/src/SFML/Window/Unix/InputImpl.cpp b/src/SFML/Window/Unix/InputImpl.cpp
index 53d92be..ad62cd5 100644
--- a/src/SFML/Window/Unix/InputImpl.cpp
+++ b/src/SFML/Window/Unix/InputImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
+// 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.
diff --git a/src/SFML/Window/Unix/InputImpl.hpp b/src/SFML/Window/Unix/InputImpl.hpp
index 9425c3d..f61647d 100644
--- a/src/SFML/Window/Unix/InputImpl.hpp
+++ b/src/SFML/Window/Unix/InputImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
+// 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.
diff --git a/src/SFML/Window/Unix/JoystickImpl.cpp b/src/SFML/Window/Unix/JoystickImpl.cpp
index d60075d..903d588 100644
--- a/src/SFML/Window/Unix/JoystickImpl.cpp
+++ b/src/SFML/Window/Unix/JoystickImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
+// 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.
@@ -440,6 +440,14 @@ namespace sf
namespace priv
{
////////////////////////////////////////////////////////////
+JoystickImpl::JoystickImpl() :
+m_file(-1)
+{
+ std::fill(m_mapping, m_mapping + ABS_MAX + 1, 0);
+}
+
+
+////////////////////////////////////////////////////////////
void JoystickImpl::initialize()
{
udevContext = udev_new();
@@ -650,19 +658,23 @@ JoystickState JoystickImpl::JoystickImpl::update()
case JS_EVENT_AXIS:
{
float value = joyState.value * 100.f / 32767.f;
- switch (m_mapping[joyState.number])
+
+ if (joyState.number < ABS_MAX + 1)
{
- case ABS_X: m_state.axes[Joystick::X] = value; break;
- case ABS_Y: m_state.axes[Joystick::Y] = value; break;
- case ABS_Z:
- case ABS_THROTTLE: m_state.axes[Joystick::Z] = value; break;
- case ABS_RZ:
- case ABS_RUDDER: m_state.axes[Joystick::R] = value; break;
- case ABS_RX: m_state.axes[Joystick::U] = value; break;
- case ABS_RY: m_state.axes[Joystick::V] = value; break;
- case ABS_HAT0X: m_state.axes[Joystick::PovX] = value; break;
- case ABS_HAT0Y: m_state.axes[Joystick::PovY] = value; break;
- default: break;
+ switch (m_mapping[joyState.number])
+ {
+ case ABS_X: m_state.axes[Joystick::X] = value; break;
+ case ABS_Y: m_state.axes[Joystick::Y] = value; break;
+ case ABS_Z:
+ case ABS_THROTTLE: m_state.axes[Joystick::Z] = value; break;
+ case ABS_RZ:
+ case ABS_RUDDER: m_state.axes[Joystick::R] = value; break;
+ case ABS_RX: m_state.axes[Joystick::U] = value; break;
+ case ABS_RY: m_state.axes[Joystick::V] = value; break;
+ case ABS_HAT0X: m_state.axes[Joystick::PovX] = value; break;
+ case ABS_HAT0Y: m_state.axes[Joystick::PovY] = value; break;
+ default: break;
+ }
}
break;
}
diff --git a/src/SFML/Window/Unix/JoystickImpl.hpp b/src/SFML/Window/Unix/JoystickImpl.hpp
index 34fce2e..e454b03 100644
--- a/src/SFML/Window/Unix/JoystickImpl.hpp
+++ b/src/SFML/Window/Unix/JoystickImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
+// 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.
@@ -45,6 +45,12 @@ class JoystickImpl
public:
////////////////////////////////////////////////////////////
+ /// \brief Constructor
+ ///
+ ////////////////////////////////////////////////////////////
+ JoystickImpl();
+
+ ////////////////////////////////////////////////////////////
/// \brief Perform the global initialization of the joystick module
///
////////////////////////////////////////////////////////////
diff --git a/src/SFML/Window/Unix/ScopedXcbPtr.hpp b/src/SFML/Window/Unix/ScopedXcbPtr.hpp
index 6c98065..f610d81 100644
--- a/src/SFML/Window/Unix/ScopedXcbPtr.hpp
+++ b/src/SFML/Window/Unix/ScopedXcbPtr.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
+// 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.
diff --git a/src/SFML/Window/Unix/ScopedXcbPtr.inl b/src/SFML/Window/Unix/ScopedXcbPtr.inl
index 6683a1e..5869d91 100644
--- a/src/SFML/Window/Unix/ScopedXcbPtr.inl
+++ b/src/SFML/Window/Unix/ScopedXcbPtr.inl
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
+// 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.
diff --git a/src/SFML/Window/Unix/SensorImpl.cpp b/src/SFML/Window/Unix/SensorImpl.cpp
index 144c6d7..fb8fce1 100644
--- a/src/SFML/Window/Unix/SensorImpl.cpp
+++ b/src/SFML/Window/Unix/SensorImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
+// 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.
diff --git a/src/SFML/Window/Unix/SensorImpl.hpp b/src/SFML/Window/Unix/SensorImpl.hpp
index 49ced87..7006377 100644
--- a/src/SFML/Window/Unix/SensorImpl.hpp
+++ b/src/SFML/Window/Unix/SensorImpl.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
+// 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.
diff --git a/src/SFML/Window/Unix/VideoModeImpl.cpp b/src/SFML/Window/Unix/VideoModeImpl.cpp
index 9ee812f..f95d323 100644
--- a/src/SFML/Window/Unix/VideoModeImpl.cpp
+++ b/src/SFML/Window/Unix/VideoModeImpl.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
+// 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.
diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp
index 7aaf4e4..88176bf 100644
--- a/src/SFML/Window/Unix/WindowImplX11.cpp
+++ b/src/SFML/Window/Unix/WindowImplX11.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
+// 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.
@@ -34,6 +34,7 @@
#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>
@@ -69,7 +70,10 @@ namespace
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_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW |
+ XCB_EVENT_MASK_VISIBILITY_CHANGE;
+
+ static const unsigned int maxTrialsCount = 5;
// Filter the events received by windows (only allow those matching a specific window)
Bool checkEvent(::Display*, XEvent* event, XPointer userData)
@@ -358,6 +362,7 @@ namespace priv
////////////////////////////////////////////////////////////
WindowImplX11::WindowImplX11(WindowHandle handle) :
m_window (0),
+m_screen (NULL),
m_inputMethod (NULL),
m_inputContext (NULL),
m_isExternal (true),
@@ -365,7 +370,9 @@ m_hiddenCursor (0),
m_keyRepeat (true),
m_previousSize (-1, -1),
m_useSizeHints (false),
-m_fullscreen (false)
+m_fullscreen (false),
+m_cursorGrabbed (false),
+m_windowMapped (false)
{
// Open a connection with the X server
m_display = OpenDisplay();
@@ -411,6 +418,7 @@ m_fullscreen (false)
////////////////////////////////////////////////////////////
WindowImplX11::WindowImplX11(VideoMode mode, const String& title, unsigned long style, const ContextSettings& settings) :
m_window (0),
+m_screen (NULL),
m_inputMethod (NULL),
m_inputContext (NULL),
m_isExternal (false),
@@ -418,7 +426,9 @@ m_hiddenCursor (0),
m_keyRepeat (true),
m_previousSize (-1, -1),
m_useSizeHints (false),
-m_fullscreen ((style & Style::Fullscreen) != 0)
+m_fullscreen ((style & Style::Fullscreen) != 0),
+m_cursorGrabbed (m_fullscreen),
+m_windowMapped (false)
{
// Open a connection with the X server
m_display = OpenDisplay();
@@ -732,7 +742,7 @@ void WindowImplX11::setTitle(const String& title)
err() << "Failed to set _NET_WM_NAME property" << std::endl;
}
- if (utf8StringType && netWmName)
+ if (utf8StringType && netWmIconName)
{
if (!changeWindowProperty(netWmIconName, utf8StringType, 8, utf8String.length(), utf8String.c_str()))
err() << "Failed to set _NET_WM_ICON_NAME property" << std::endl;
@@ -909,6 +919,13 @@ void WindowImplX11::setVisible(bool visible)
if (error)
err() << "Failed to change window visibility" << std::endl;
+
+ xcb_flush(m_connection);
+
+ // Before continuing, make sure the WM has
+ // internally marked the window as viewable
+ while (!m_windowMapped)
+ processEvents();
}
else
{
@@ -922,9 +939,14 @@ void WindowImplX11::setVisible(bool visible)
if (error)
err() << "Failed to change window visibility" << std::endl;
- }
- xcb_flush(m_connection);
+ xcb_flush(m_connection);
+
+ // Before continuing, make sure the WM has
+ // internally marked the window as unviewable
+ while (m_windowMapped)
+ processEvents();
+ }
}
@@ -951,6 +973,71 @@ void WindowImplX11::setMouseCursorVisible(bool visible)
////////////////////////////////////////////////////////////
+void WindowImplX11::setMouseCursorGrabbed(bool grabbed)
+{
+ // This has no effect in fullscreen mode
+ if (m_fullscreen || (m_cursorGrabbed == grabbed))
+ return;
+
+ if (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);
+
+ 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))
+ {
+ m_cursorGrabbed = true;
+ break;
+ }
+
+ // The cursor grab failed, trying again after a small sleep
+ sf::sleep(sf::milliseconds(50));
+ }
+
+ if (!m_cursorGrabbed)
+ err() << "Failed to grab mouse cursor" << std::endl;
+ }
+ 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;
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////////////
void WindowImplX11::setKeyRepeatEnabled(bool enabled)
{
m_keyRepeat = enabled;
@@ -1604,7 +1691,7 @@ void WindowImplX11::cleanup()
////////////////////////////////////////////////////////////
-bool WindowImplX11::processEvent(XEvent windowEvent)
+bool WindowImplX11::processEvent(XEvent& windowEvent)
{
// This function implements a workaround to properly discard
// repeated key events when necessary. The problem is that the
@@ -1659,6 +1746,44 @@ bool WindowImplX11::processEvent(XEvent windowEvent)
if (m_inputContext)
XSetICFocus(m_inputContext);
+ // Grab cursor
+ if (m_cursorGrabbed)
+ {
+ // 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
+ ));
+
+ if (!error && grabPointerReply && (grabPointerReply->status == XCB_GRAB_STATUS_SUCCESS))
+ {
+ m_cursorGrabbed = true;
+ break;
+ }
+
+ // The cursor grab failed, trying again after a small sleep
+ sf::sleep(sf::milliseconds(50));
+ }
+
+ if (!m_cursorGrabbed)
+ err() << "Failed to grab mouse cursor" << std::endl;
+ }
+
Event event;
event.type = Event::GainedFocus;
pushEvent(event);
@@ -1701,6 +1826,21 @@ bool WindowImplX11::processEvent(XEvent windowEvent)
if (m_inputContext)
XUnsetICFocus(m_inputContext);
+ // 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;
+ }
+
Event event;
event.type = Event::LostFocus;
pushEvent(event);
@@ -1757,17 +1897,23 @@ bool WindowImplX11::processEvent(XEvent windowEvent)
// Key down event
case KeyPress:
{
- // Get the keysym of the key that has been pressed
- static XComposeStatus keyboard;
- char buffer[32];
- KeySym symbol;
- XLookupString(&windowEvent.xkey, buffer, sizeof(buffer), &symbol, &keyboard);
+ Keyboard::Key key = Keyboard::Unknown;
+
+ // Try each KeySym index (modifier group) until we get a match
+ for (int i = 0; i < 4; ++i)
+ {
+ // Get the SFML keyboard code from the keysym of the key that has been pressed
+ key = keysymToSF(XLookupKeysym(&windowEvent.xkey, i));
+
+ if (key != Keyboard::Unknown)
+ break;
+ }
// Fill the event parameters
// TODO: if modifiers are wrong, use XGetModifierMapping to retrieve the actual modifiers mapping
Event event;
event.type = Event::KeyPressed;
- event.key.code = keysymToSF(symbol);
+ event.key.code = key;
event.key.alt = windowEvent.xkey.state & Mod1Mask;
event.key.control = windowEvent.xkey.state & ControlMask;
event.key.shift = windowEvent.xkey.state & ShiftMask;
@@ -1826,15 +1972,22 @@ bool WindowImplX11::processEvent(XEvent windowEvent)
// Key up event
case KeyRelease:
{
- // Get the keysym of the key that has been pressed
- char buffer[32];
- KeySym symbol;
- XLookupString(&windowEvent.xkey, buffer, 32, &symbol, NULL);
+ Keyboard::Key key = Keyboard::Unknown;
+
+ // Try each KeySym index (modifier group) until we get a match
+ for (int i = 0; i < 4; ++i)
+ {
+ // Get the SFML keyboard code from the keysym of the key that has been released
+ key = keysymToSF(XLookupKeysym(&windowEvent.xkey, i));
+
+ if (key != Keyboard::Unknown)
+ break;
+ }
// Fill the event parameters
Event event;
event.type = Event::KeyReleased;
- event.key.code = keysymToSF(symbol);
+ event.key.code = key;
event.key.alt = windowEvent.xkey.state & Mod1Mask;
event.key.control = windowEvent.xkey.state & ControlMask;
event.key.shift = windowEvent.xkey.state & ShiftMask;
@@ -1962,16 +2115,33 @@ bool WindowImplX11::processEvent(XEvent windowEvent)
break;
}
- // Parent window changed
- case ReparentNotify:
+ // Window unmapped
+ case UnmapNotify:
{
- // Catch reparent events to properly apply fullscreen on
- // some "strange" window managers (like Awesome) which
- // seem to make use of temporary parents during mapping
- if (m_fullscreen)
- switchToFullscreen();
+ if (windowEvent.xunmap.window == m_window)
+ m_windowMapped = false;
+
+ break;
+ }
+
+ // Window visibility change
+ case VisibilityNotify:
+ {
+ // We prefer using VisibilityNotify over MapNotify because
+ // some window managers like awesome don't internally flag a
+ // window as viewable even after it is mapped but before it
+ // is visible leading to certain function calls failing with
+ // an unviewable error if called before VisibilityNotify arrives
+
+ // Empirical testing on most widely used window managers shows
+ // that mapping a window will always lead to a VisibilityNotify
+ // event that is not VisibilityFullyObscured
+ if (windowEvent.xvisibility.window == m_window)
+ {
+ if (windowEvent.xvisibility.state != VisibilityFullyObscured)
+ m_windowMapped = true;
+ }
- XSync(m_display, True); // Discard remaining events
break;
}
}
diff --git a/src/SFML/Window/Unix/WindowImplX11.hpp b/src/SFML/Window/Unix/WindowImplX11.hpp
index a717bfb..ea6f741 100644
--- a/src/SFML/Window/Unix/WindowImplX11.hpp
+++ b/src/SFML/Window/Unix/WindowImplX11.hpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
+// 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.
@@ -148,6 +148,14 @@ public:
virtual void setMouseCursorVisible(bool visible);
////////////////////////////////////////////////////////////
+ /// \brief Grab or release the mouse cursor
+ ///
+ /// \param grabbed True to enable, false to disable
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void setMouseCursorGrabbed(bool grabbed);
+
+ ////////////////////////////////////////////////////////////
/// \brief Enable or disable automatic key-repeat
///
/// \param enabled True to enable, false to disable
@@ -301,7 +309,7 @@ private:
/// \return True if the event was processed, false if it was discarded
///
////////////////////////////////////////////////////////////
- bool processEvent(XEvent windowEvent);
+ bool processEvent(XEvent& windowEvent);
////////////////////////////////////////////////////////////
// Member data
@@ -318,7 +326,9 @@ private:
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 window in fullscreen?
+ 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?
};
} // namespace priv