diff --git a/src/SFML/Window/CMakeLists.txt b/src/SFML/Window/CMakeLists.txt index c26d70091..591dff731 100644 --- a/src/SFML/Window/CMakeLists.txt +++ b/src/SFML/Window/CMakeLists.txt @@ -51,6 +51,8 @@ if(WINDOWS) elseif(LINUX) set(SRC ${SRC} + ${SRCROOT}/Linux/Display.cpp + ${SRCROOT}/Linux/Display.hpp ${SRCROOT}/Linux/GlxContext.cpp ${SRCROOT}/Linux/GlxContext.hpp ${SRCROOT}/Linux/InputImpl.cpp diff --git a/src/SFML/Window/Linux/Display.cpp b/src/SFML/Window/Linux/Display.cpp new file mode 100644 index 000000000..24202688b --- /dev/null +++ b/src/SFML/Window/Linux/Display.cpp @@ -0,0 +1,65 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2012 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace +{ + // The shared display and its reference counter + Display* sharedDisplay = NULL; + unsigned int referenceCount = 0; +} + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +Display* OpenDisplay() +{ + if (referenceCount == 0) + sharedDisplay = XOpenDisplay(NULL); + referenceCount++; + return sharedDisplay; +} + + +//////////////////////////////////////////////////////////// +void CloseDisplay(Display* display) +{ + assert(display == sharedDisplay); + + referenceCount--; + if (referenceCount == 0) + XCloseDisplay(display); +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Window/Linux/Display.hpp b/src/SFML/Window/Linux/Display.hpp new file mode 100644 index 000000000..b45b4a0d4 --- /dev/null +++ b/src/SFML/Window/Linux/Display.hpp @@ -0,0 +1,62 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2012 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SHAREDDISPLAY_HPP +#define SFML_SHAREDDISPLAY_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Get the shared Display +/// +/// This function increments the reference count of the display, +/// it must be matched with a call to CloseDisplay. +/// +/// \return Pointer to the shared display +/// +//////////////////////////////////////////////////////////// +Display* OpenDisplay(); + +//////////////////////////////////////////////////////////// +/// \brief Release a reference to the shared +/// +/// \param display Display to release +/// +//////////////////////////////////////////////////////////// +void CloseDisplay(Display* display); + +} // namespace priv + +} // namespace sf + + +#endif // SFML_SHAREDDISPLAY_HPP diff --git a/src/SFML/Window/Linux/GlxContext.cpp b/src/SFML/Window/Linux/GlxContext.cpp index 61b297f54..dac28989f 100644 --- a/src/SFML/Window/Linux/GlxContext.cpp +++ b/src/SFML/Window/Linux/GlxContext.cpp @@ -28,6 +28,7 @@ #define GLX_GLXEXT_LEGACY // so that our local glxext.h is used instead of the system one #include #include +#include #include #include #include @@ -39,12 +40,11 @@ namespace priv { //////////////////////////////////////////////////////////// GlxContext::GlxContext(GlxContext* shared) : -m_window (0), -m_context (NULL), -m_ownsWindow(true) +m_window (0), +m_context(NULL) { // Open a connection with the X server - m_display = XOpenDisplay(NULL); + m_display = OpenDisplay(); // Create a dummy window (disabled and hidden) int screen = DefaultScreen(m_display); @@ -65,12 +65,12 @@ m_ownsWindow(true) //////////////////////////////////////////////////////////// GlxContext::GlxContext(GlxContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) : -m_window (0), -m_context (NULL), -m_ownsWindow(false) +m_window (0), +m_context(NULL) { - // Use the same display as the owner window (important!) - m_display = static_cast(owner)->getDisplay(); + // Open a connection with the X server + // (important: must be the same display as the owner window) + m_display = OpenDisplay(); // Get the owner window and its device context m_window = static_cast< ::Window>(owner->getSystemHandle()); @@ -83,12 +83,11 @@ m_ownsWindow(false) //////////////////////////////////////////////////////////// GlxContext::GlxContext(GlxContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height) : -m_window (0), -m_context (NULL), -m_ownsWindow(true) +m_window (0), +m_context(NULL) { // Open a connection with the X server - m_display = XOpenDisplay(NULL); + m_display = OpenDisplay(); // Create the hidden window int screen = DefaultScreen(m_display); @@ -119,15 +118,14 @@ GlxContext::~GlxContext() } // Destroy the window if we own it - if (m_window && m_ownsWindow) + if (m_window) { XDestroyWindow(m_display, m_window); XFlush(m_display); } - + // Close the connection with the X server - if (m_ownsWindow) - XCloseDisplay(m_display); + CloseDisplay(m_display); } diff --git a/src/SFML/Window/Linux/InputImpl.cpp b/src/SFML/Window/Linux/InputImpl.cpp index 262387041..f2518038c 100644 --- a/src/SFML/Window/Linux/InputImpl.cpp +++ b/src/SFML/Window/Linux/InputImpl.cpp @@ -27,34 +27,11 @@ //////////////////////////////////////////////////////////// #include #include +#include #include #include -namespace -{ - // Open, store and close a X display - struct GlobalDisplay - { - GlobalDisplay() - { - display = XOpenDisplay(NULL); - window = DefaultRootWindow(display); - } - - ~GlobalDisplay() - { - XCloseDisplay(display); - } - - ::Display* display; - ::Window window; - }; - - // Global connection with the X server, used in global input functions - GlobalDisplay global; -} - namespace sf { namespace priv @@ -170,32 +147,49 @@ bool InputImpl::isKeyPressed(Keyboard::Key key) default: keysym = 0; break; } + // Open a connection with the X server + Display* display = OpenDisplay(); + // Convert to keycode - KeyCode keycode = XKeysymToKeycode(global.display, keysym); + KeyCode keycode = XKeysymToKeycode(display, keysym); if (keycode != 0) { // Get the whole keyboard state char keys[32]; - XQueryKeymap(global.display, keys); + XQueryKeymap(display, keys); + + // Close the connection with the X server + CloseDisplay(display); // Check our keycode return (keys[keycode / 8] & (1 << (keycode % 8))) != 0; } + else + { + // Close the connection with the X server + CloseDisplay(display); - return false; + return false; + } } //////////////////////////////////////////////////////////// bool InputImpl::isMouseButtonPressed(Mouse::Button button) { + // Open a connection with the X server + Display* display = OpenDisplay(); + // we don't care about these but they are required ::Window root, child; int wx, wy; int gx, gy; unsigned int buttons = 0; - XQueryPointer(global.display, global.window, &root, &child, &gx, &gy, &wx, &wy, &buttons); + XQueryPointer(display, DefaultRootWindow(display), &root, &child, &gx, &gy, &wx, &wy, &buttons); + + // Close the connection with the X server + CloseDisplay(display); switch (button) { @@ -214,6 +208,9 @@ bool InputImpl::isMouseButtonPressed(Mouse::Button button) //////////////////////////////////////////////////////////// Vector2i InputImpl::getMousePosition() { + // Open a connection with the X server + Display* display = OpenDisplay(); + // we don't care about these but they are required ::Window root, child; int x, y; @@ -221,7 +218,10 @@ Vector2i InputImpl::getMousePosition() int gx = 0; int gy = 0; - XQueryPointer(global.display, global.window, &root, &child, &gx, &gy, &x, &y, &buttons); + XQueryPointer(display, DefaultRootWindow(display), &root, &child, &gx, &gy, &x, &y, &buttons); + + // Close the connection with the X server + CloseDisplay(display); return Vector2i(gx, gy); } @@ -233,6 +233,9 @@ Vector2i InputImpl::getMousePosition(const Window& relativeTo) WindowHandle handle = relativeTo.getSystemHandle(); if (handle) { + // Open a connection with the X server + Display* display = OpenDisplay(); + // we don't care about these but they are required ::Window root, child; int gx, gy; @@ -240,7 +243,10 @@ Vector2i InputImpl::getMousePosition(const Window& relativeTo) int x = 0; int y = 0; - XQueryPointer(global.display, handle, &root, &child, &gx, &gy, &x, &y, &buttons); + XQueryPointer(display, handle, &root, &child, &gx, &gy, &x, &y, &buttons); + + // Close the connection with the X server + CloseDisplay(display); return Vector2i(x, y); } @@ -254,20 +260,32 @@ Vector2i InputImpl::getMousePosition(const Window& relativeTo) //////////////////////////////////////////////////////////// void InputImpl::setMousePosition(const Vector2i& position) { - XWarpPointer(global.display, None, global.window, 0, 0, 0, 0, position.x, position.y); - XFlush(global.display); + // Open a connection with the X server + Display* display = OpenDisplay(); + + XWarpPointer(display, None, DefaultRootWindow(display), 0, 0, 0, 0, position.x, position.y); + XFlush(display); + + // Close the connection with the X server + CloseDisplay(display); } //////////////////////////////////////////////////////////// void InputImpl::setMousePosition(const Vector2i& position, const Window& relativeTo) { + // Open a connection with the X server + Display* display = OpenDisplay(); + WindowHandle handle = relativeTo.getSystemHandle(); if (handle) { - XWarpPointer(global.display, None, handle, 0, 0, 0, 0, position.x, position.y); - XFlush(global.display); + XWarpPointer(display, None, handle, 0, 0, 0, 0, position.x, position.y); + XFlush(display); } + + // Close the connection with the X server + CloseDisplay(display); } } // namespace priv diff --git a/src/SFML/Window/Linux/VideoModeImpl.cpp b/src/SFML/Window/Linux/VideoModeImpl.cpp index 6932f2870..0b8aca897 100644 --- a/src/SFML/Window/Linux/VideoModeImpl.cpp +++ b/src/SFML/Window/Linux/VideoModeImpl.cpp @@ -26,6 +26,7 @@ // Headers //////////////////////////////////////////////////////////// #include +#include #include #include #include @@ -42,18 +43,18 @@ std::vector VideoModeImpl::getFullscreenModes() std::vector modes; // Open a connection with the X server - Display* disp = XOpenDisplay(NULL); - if (disp) + Display* display = OpenDisplay(); + if (display) { // Retrieve the default screen number - int screen = DefaultScreen(disp); + int screen = DefaultScreen(display); // Check if the XRandR extension is present int version; - if (XQueryExtension(disp, "RANDR", &version, &version, &version)) + if (XQueryExtension(display, "RANDR", &version, &version, &version)) { // Get the current configuration - XRRScreenConfiguration* config = XRRGetScreenInfo(disp, RootWindow(disp, screen)); + XRRScreenConfiguration* config = XRRGetScreenInfo(display, RootWindow(display, screen)); if (config) { // Get the available screen sizes @@ -63,7 +64,7 @@ std::vector VideoModeImpl::getFullscreenModes() { // Get the list of supported depths int nbDepths = 0; - int* depths = XListDepths(disp, screen, &nbDepths); + int* depths = XListDepths(display, screen, &nbDepths); if (depths && (nbDepths > 0)) { // Combine depths and sizes to fill the array of supported modes @@ -101,7 +102,7 @@ std::vector VideoModeImpl::getFullscreenModes() } // Close the connection with the X server - XCloseDisplay(disp); + CloseDisplay(display); } else { @@ -119,18 +120,18 @@ VideoMode VideoModeImpl::getDesktopMode() VideoMode desktopMode; // Open a connection with the X server - Display* disp = XOpenDisplay(NULL); - if (disp) + Display* display = OpenDisplay(); + if (display) { // Retrieve the default screen number - int screen = DefaultScreen(disp); + int screen = DefaultScreen(display); // Check if the XRandR extension is present int version; - if (XQueryExtension(disp, "RANDR", &version, &version, &version)) + if (XQueryExtension(display, "RANDR", &version, &version, &version)) { // Get the current configuration - XRRScreenConfiguration* config = XRRGetScreenInfo(disp, RootWindow(disp, screen)); + XRRScreenConfiguration* config = XRRGetScreenInfo(display, RootWindow(display, screen)); if (config) { // Get the current video mode @@ -141,7 +142,7 @@ VideoMode VideoModeImpl::getDesktopMode() int nbSizes; XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes); if (sizes && (nbSizes > 0)) - desktopMode = VideoMode(sizes[currentMode].width, sizes[currentMode].height, DefaultDepth(disp, screen)); + desktopMode = VideoMode(sizes[currentMode].width, sizes[currentMode].height, DefaultDepth(display, screen)); // Free the configuration instance XRRFreeScreenConfigInfo(config); @@ -159,7 +160,7 @@ VideoMode VideoModeImpl::getDesktopMode() } // Close the connection with the X server - XCloseDisplay(disp); + CloseDisplay(display); } else { diff --git a/src/SFML/Window/Linux/WindowImplX11.cpp b/src/SFML/Window/Linux/WindowImplX11.cpp index c6f8391e1..44d524902 100644 --- a/src/SFML/Window/Linux/WindowImplX11.cpp +++ b/src/SFML/Window/Linux/WindowImplX11.cpp @@ -27,6 +27,7 @@ //////////////////////////////////////////////////////////// #include // important to be included first (conflict with None) #include +#include #include #include #include @@ -72,7 +73,7 @@ m_hiddenCursor(0), m_keyRepeat (true) { // Open a connection with the X server - m_display = XOpenDisplay(NULL); + m_display = OpenDisplay(); m_screen = DefaultScreen(m_display); // Save the window handle @@ -101,7 +102,7 @@ m_hiddenCursor(0), m_keyRepeat (true) { // Open a connection with the X server - m_display = XOpenDisplay(NULL); + m_display = OpenDisplay(); m_screen = DefaultScreen(m_display); // Compute position and size @@ -255,14 +256,7 @@ WindowImplX11::~WindowImplX11() XCloseIM(m_inputMethod); // Close the connection with the X server - XCloseDisplay(m_display); -} - - -//////////////////////////////////////////////////////////// -::Display* WindowImplX11::getDisplay() const -{ - return m_display; + CloseDisplay(m_display); } diff --git a/src/SFML/Window/Linux/WindowImplX11.hpp b/src/SFML/Window/Linux/WindowImplX11.hpp index d57177fdb..11c7e6ef3 100644 --- a/src/SFML/Window/Linux/WindowImplX11.hpp +++ b/src/SFML/Window/Linux/WindowImplX11.hpp @@ -71,16 +71,6 @@ public : //////////////////////////////////////////////////////////// ~WindowImplX11(); - //////////////////////////////////////////////////////////// - /// \brief Get the display used by the window - /// - /// This functions is meant to be used internally by ContextGLX. - /// - /// \return Pointer to the X display of the window - /// - //////////////////////////////////////////////////////////// - ::Display* getDisplay() const; - //////////////////////////////////////////////////////////// /// \brief Get the OS-specific handle of the window ///