diff options
author | James Cowgill <jcowgill@debian.org> | 2016-08-09 15:20:03 +0000 |
---|---|---|
committer | James Cowgill <jcowgill@debian.org> | 2016-08-09 15:20:03 +0000 |
commit | df93e238e30e97850d76ad5585b8ab9ad9c03e67 (patch) | |
tree | 2ae5f3305e1ee1882f563d2803f94aa6446dc367 /src/SFML/Window/Unix | |
parent | 301fd78b3ac87cf1fbce9d2c955db89094a304a5 (diff) |
Imported Upstream version 2.4.0+dfsg
Diffstat (limited to 'src/SFML/Window/Unix')
-rw-r--r-- | src/SFML/Window/Unix/Display.cpp | 2 | ||||
-rw-r--r-- | src/SFML/Window/Unix/Display.hpp | 2 | ||||
-rw-r--r-- | src/SFML/Window/Unix/GlxContext.cpp | 451 | ||||
-rw-r--r-- | src/SFML/Window/Unix/GlxContext.hpp | 40 | ||||
-rw-r--r-- | src/SFML/Window/Unix/GlxExtensions.cpp | 135 | ||||
-rw-r--r-- | src/SFML/Window/Unix/GlxExtensions.hpp | 89 | ||||
-rw-r--r-- | src/SFML/Window/Unix/GlxExtensions.txt | 9 | ||||
-rw-r--r-- | src/SFML/Window/Unix/InputImpl.cpp | 2 | ||||
-rw-r--r-- | src/SFML/Window/Unix/InputImpl.hpp | 2 | ||||
-rw-r--r-- | src/SFML/Window/Unix/JoystickImpl.cpp | 38 | ||||
-rw-r--r-- | src/SFML/Window/Unix/JoystickImpl.hpp | 8 | ||||
-rw-r--r-- | src/SFML/Window/Unix/ScopedXcbPtr.hpp | 2 | ||||
-rw-r--r-- | src/SFML/Window/Unix/ScopedXcbPtr.inl | 2 | ||||
-rw-r--r-- | src/SFML/Window/Unix/SensorImpl.cpp | 2 | ||||
-rw-r--r-- | src/SFML/Window/Unix/SensorImpl.hpp | 2 | ||||
-rw-r--r-- | src/SFML/Window/Unix/VideoModeImpl.cpp | 2 | ||||
-rw-r--r-- | src/SFML/Window/Unix/WindowImplX11.cpp | 224 | ||||
-rw-r--r-- | src/SFML/Window/Unix/WindowImplX11.hpp | 16 |
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 |