From 135c1716e877464db720265f37316cbb54ef13f2 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Sun, 25 Nov 2012 11:54:45 +0100 Subject: [PATCH] Replaced Xlib by XCB implementation. * Added FindXCB.cmake script * Added AutoPointer wrapper for automatically free'ing pointers * Huge commit: Ported linux implementation of sfml-window to xcb * Xcb is now used for window creation, event loop etc * As GLX is linked to Xlib, that part of the implementation still uses Xlib. * Also, some keyboard related (such as XLookupString) stuff is still Xlib, as xcb does not have it (yet?). * Replaced some enums with the xcb equivalents --- cmake/Modules/FindXCB.cmake | 97 +++++ src/SFML/Window/CMakeLists.txt | 19 +- src/SFML/Window/Linux/AutoPointer.cpp | 44 +++ src/SFML/Window/Linux/AutoPointer.hpp | 132 +++++++ src/SFML/Window/Unix/Display.cpp | 28 ++ src/SFML/Window/Unix/Display.hpp | 35 +- src/SFML/Window/Unix/GlxContext.cpp | 219 +++++++---- src/SFML/Window/Unix/GlxContext.hpp | 11 +- src/SFML/Window/Unix/InputImpl.cpp | 75 ++-- src/SFML/Window/Unix/VideoModeImpl.cpp | 95 ++--- src/SFML/Window/Unix/WindowImplX11.cpp | 511 ++++++++++++++----------- src/SFML/Window/Unix/WindowImplX11.hpp | 31 +- 12 files changed, 862 insertions(+), 435 deletions(-) create mode 100644 cmake/Modules/FindXCB.cmake create mode 100644 src/SFML/Window/Linux/AutoPointer.cpp create mode 100644 src/SFML/Window/Linux/AutoPointer.hpp diff --git a/cmake/Modules/FindXCB.cmake b/cmake/Modules/FindXCB.cmake new file mode 100644 index 000000000..d69146104 --- /dev/null +++ b/cmake/Modules/FindXCB.cmake @@ -0,0 +1,97 @@ +# Try to find libxcb +# +# +# Once done this will define: +# LIBXCB_FOUND - True if xcb was found +# LIBXCB_INCLUDE_DIRS - Directories containing the headers +# LIBXCB_LIBRARIES - List of libraries to link to +# +# Also for each requested component: +# LIBXCB_${UPPER_COMPONENT_NAME}_FOUND +# LIBXCB_${UPPER_COMPONENT_NAME}_INCLUDE_DIRS +# LIBXCB_${UPPER_COMPONENT_NAME}_LIBRARIES + +include(FindPackageHandleStandardArgs) + +IF(NOT WIN32) + IF(LIBXCB_LIBRARIES AND LIBXCB_INCLUDE_DIR) + set(XCB_FIND_QUIETLY TRUE) + ENDIF() + + # Find xcb + FIND_PATH(LIBXCB_INCLUDE_DIR xcb/xcb.h) + FIND_LIBRARY(LIBXCB_LIBRARY NAMES xcb libxcb) + + # Add xcb info to LIBXCB_LIBRARIES and LIBXCB_INCLUDE_DIRS + SET(LIBXCB_LIBRARIES ${LIBXCB_LIBRARY}) + SET(LIBXCB_INCLUDE_DIRS ${LIBXCB_INCLUDE_DIR}) + + find_package_handle_standard_args(LIBXCB DEFAULT_MSG + LIBXCB_LIBRARY LIBXCB_INCLUDE_DIR) + + mark_as_advanced(LIBXCB_LIBRARY LIBXCB_INCLUDE_DIR) + + # Check whether we should search for XLIB_XCB + set(FIND_XLIB_XCB FALSE) + FOREACH(XCB_COMPONENT ${XCB_FIND_COMPONENTS}) + # Generate upper string of the component name + string(TOUPPER ${XCB_COMPONENT} XCB_COMPONENT_UPPER) + + IF(${XCB_COMPONENT_UPPER} MATCHES "XLIB_XCB") + set(FIND_XLIB_XCB TRUE) + ELSE() + # XCB_COMPONENTS is generated to be a copy of XCB_FIND_COMPONENTS + # without XLIB_XCB (for later component search) + set(XCB_COMPONENTS ${XCB_COMPONENTS} ${XCB_COMPONENT}) + ENDIF() + ENDFOREACH() + + # Find XLIB_XCB if requested + IF(FIND_XLIB_XCB) + FIND_PATH(XLIB_XCB_INCLUDE_DIR X11/Xlib-xcb.h) + FIND_LIBRARY(XLIB_XCB_LIBRARY NAMES X11-xcb libX11-xcb) + + SET(XLIB_XCB_LIBRARIES ${XLIB_XCB_LIBRARY}) + SET(XLIB_XCB_INCLUDE_DIRS ${XLIB_XCB_INCLUDE_DIR}) + + find_package_handle_standard_args(XLIB_XCB DEFAULT_MSG + XLIB_XCB_LIBRARY LIBXCB_INCLUDE_DIR) + + mark_as_advanced(XLIB_XCB_LIBRARY XLIB_XCB_INCLUDE_DIR) + + # Add xlib_xcb info to LIBXCB_LIBRARIES and LIBXCB_INCLUDE_DIRS + set(LIBXCB_LIBRARIES ${LIBXCB_LIBRARIES} ${XLIB_XCB_LIBRARIES}) + set(LIBXCB_INCLUDE_DIRS ${LIBXCB_INCLUDE_DIRS} ${XLIB_XCB_INCLUDE_DIR}) + + if(NOT XLIB_XCB_FOUND) + message(FATAL_ERROR "XlibXcb library not found") + endif() + ELSE() + # Add component name to the component list + set(${XCB_COMPONENTS} ${XCB_FIND_COMPONENTS}) + ENDIF() + + # Loop through requested xcb components (does not contain xlib_xcb) + FOREACH(XCB_COMPONENT ${XCB_COMPONENTS}) + # Generate lower and upper string of the component name + string(TOLOWER ${XCB_COMPONENT} XCB_COMPONENT_LOWER) + string(TOUPPER ${XCB_COMPONENT} XCB_COMPONENT_UPPER) + + # Find the specific component + FIND_LIBRARY(LIBXCB_${XCB_COMPONENT_UPPER}_LIBRARY + NAMES libxcb-${XCB_COMPONENT_LOWER} xcb-${XCB_COMPONENT_LOWER}) + + find_package_handle_standard_args(LIBXCB_${XCB_COMPONENT_UPPER} DEFAULT_MSG + LIBXCB_${XCB_COMPONENT_UPPER}_LIBRARY LIBXCB_INCLUDE_DIR) + + mark_as_advanced(LIBXCB_${XCB_COMPONENT_UPPER}_LIBRARY) + + # Append the component's library path to LIBXCB_LIBRARIES + set(LIBXCB_LIBRARIES ${LIBXCB_LIBRARIES} ${LIBXCB_${XCB_COMPONENT_UPPER}_LIBRARY}) + + if(NOT LIBXCB_${XCB_COMPONENT_UPPER}_FOUND) + message(FATAL_ERROR "xcb-${XCB_COMPONENT_LOWER} not found") + endif() + ENDFOREACH() + +endif() diff --git a/src/SFML/Window/CMakeLists.txt b/src/SFML/Window/CMakeLists.txt index 3046fec67..20fb2b313 100644 --- a/src/SFML/Window/CMakeLists.txt +++ b/src/SFML/Window/CMakeLists.txt @@ -69,6 +69,8 @@ if(SFML_OS_WINDOWS) add_definitions(-DUNICODE -D_UNICODE) elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD) set(PLATFORM_SRC + ${SRCROOT}/Linux/AutoPointer.cpp + ${SRCROOT}/Linux/AutoPointer.hpp ${SRCROOT}/Unix/Display.cpp ${SRCROOT}/Unix/Display.hpp ${SRCROOT}/Unix/InputImpl.cpp @@ -193,11 +195,11 @@ if(NOT SFML_OPENGL_ES) find_package(OpenGL REQUIRED) include_directories(${OPENGL_INCLUDE_DIR}) if(SFML_OS_LINUX OR SFML_OS_FREEBSD) - find_package(X11 REQUIRED) - if(NOT X11_Xrandr_FOUND) - message(FATAL_ERROR "Xrandr library not found") + find_package(XCB COMPONENTS xlib_xcb atom icccm image randr REQUIRED) + if(NOT LIBXCB_FOUND) + message(FATAL_ERROR "Xcb library not found") endif() - include_directories(${X11_INCLUDE_DIR}) + include_directories(${LIBXCB_INCLUDE_DIRS}) endif() endif() if(SFML_OPENGL_ES AND SFML_OS_LINUX) @@ -217,10 +219,11 @@ endif() # build the list of external libraries to link if(SFML_OS_WINDOWS) list(APPEND WINDOW_EXT_LIBS winmm gdi32) -elseif(SFML_OS_LINUX) - list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${X11_Xrandr_LIB} ${UDEV_LIBRARIES}) -elseif(SFML_OS_FREEBSD) - list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${X11_Xrandr_LIB} usbhid) +elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD) + list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${X11_Xrandr_LIB} ${LIBXCB_LIBRARIES} ${UDEV_LIBRARIES}) + if(SFML_OS_FREEBSD) + list(APPEND WINDOW_EXT_LIBS usbhid) + endif() elseif(SFML_OS_MACOSX) list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework AppKit -framework IOKit -framework Carbon") elseif(SFML_OS_IOS) diff --git a/src/SFML/Window/Linux/AutoPointer.cpp b/src/SFML/Window/Linux/AutoPointer.cpp new file mode 100644 index 000000000..e20d01d6b --- /dev/null +++ b/src/SFML/Window/Linux/AutoPointer.cpp @@ -0,0 +1,44 @@ +//////////////////////////////////////////////////////////// +// +// 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 sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +ErrorPointer::ErrorPointer(xcb_connection_t *&connection, xcb_void_cookie_t &cookie) + : AutoPointer(xcb_request_check(connection, cookie)) +{ +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Window/Linux/AutoPointer.hpp b/src/SFML/Window/Linux/AutoPointer.hpp new file mode 100644 index 000000000..0d9296823 --- /dev/null +++ b/src/SFML/Window/Linux/AutoPointer.hpp @@ -0,0 +1,132 @@ +//////////////////////////////////////////////////////////// +// +// 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 AUTOPOINTER_HPP +#define AUTOPOINTER_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Pointer Wrapper. Memory is automatically free'd +/// on deletion of the object. +/// +//////////////////////////////////////////////////////////// +template +class AutoPointer +{ +public: + //////////////////////////////////////////////////////////// + /// \brief Constructor + /// + //////////////////////////////////////////////////////////// + AutoPointer(T* ptr) + { + pointer = ptr; + } + + //////////////////////////////////////////////////////////// + /// \brief Constructor + /// + //////////////////////////////////////////////////////////// + AutoPointer() + : pointer(NULL) + { + } + + //////////////////////////////////////////////////////////// + /// \brief Destructor, frees the error pointer + /// + //////////////////////////////////////////////////////////// + ~AutoPointer() + { + free(pointer); + } + + //////////////////////////////////////////////////////////// + /// \brief Operator for error member access + /// + //////////////////////////////////////////////////////////// + T* operator->() const + { + return pointer; + } + + //////////////////////////////////////////////////////////// + /// \brief Assignment operator. Frees the previous pointer + /// + //////////////////////////////////////////////////////////// + T* operator=(T*& new_pointer) const + { + free(pointer); + pointer = new_pointer; + } + + T** operator&() + { + return &pointer; + } + + //////////////////////////////////////////////////////////// + /// \brief Check if reqeust succeeded + /// + /// \return true if reqeust succeeded + /// + //////////////////////////////////////////////////////////// + bool isNull() const + { + return pointer == NULL; + } + +private: + T* pointer; +}; + + +//////////////////////////////////////////////////////////// +/// \brief Wrapper for automatically creating and freeing +/// an error struct out of a cookie +/// +//////////////////////////////////////////////////////////// +class ErrorPointer : public AutoPointer +{ +public: + //////////////////////////////////////////////////////////// + /// \brief Construct the error pointer from a cookie + /// + //////////////////////////////////////////////////////////// + ErrorPointer(xcb_connection_t*& connection, xcb_void_cookie_t& cookie); +}; + +} // namespace priv + +} // namespace sf + +#endif // AUTOPOINTER_HPP diff --git a/src/SFML/Window/Unix/Display.cpp b/src/SFML/Window/Unix/Display.cpp index aad1b2672..fddba3073 100644 --- a/src/SFML/Window/Unix/Display.cpp +++ b/src/SFML/Window/Unix/Display.cpp @@ -63,6 +63,13 @@ Display* OpenDisplay() } +//////////////////////////////////////////////////////////// +xcb_connection_t* OpenConnection() +{ + return XGetXCBConnection(OpenDisplay()); +} + + //////////////////////////////////////////////////////////// void CloseDisplay(Display* display) { @@ -73,6 +80,27 @@ void CloseDisplay(Display* display) XCloseDisplay(display); } +//////////////////////////////////////////////////////////// +void CloseConnection(xcb_connection_t* connection) +{ + assert(connection == XGetXCBConnection(sharedDisplay)); + return CloseDisplay(sharedDisplay); +} + +//////////////////////////////////////////////////////////// +xcb_screen_t* XCBScreenOfDisplay(xcb_connection_t* connection, int screen_nbr) +{ + xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_get_setup(connection)); + + for (; iter.rem; --screen_nbr, xcb_screen_next (&iter)) + { + if (screen_nbr == 0) + return iter.data; + } + + return NULL; +} + } // namespace priv } // namespace sf diff --git a/src/SFML/Window/Unix/Display.hpp b/src/SFML/Window/Unix/Display.hpp index df018b391..6d213f0bf 100644 --- a/src/SFML/Window/Unix/Display.hpp +++ b/src/SFML/Window/Unix/Display.hpp @@ -28,7 +28,7 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include +#include namespace sf @@ -47,13 +47,42 @@ namespace priv Display* OpenDisplay(); //////////////////////////////////////////////////////////// -/// \brief Release a reference to the shared +/// \brief Get the xcb connection of the shared Display /// -/// \param display Display to release +/// This function increments the reference count of the display, +/// it must be matched with a call to CloseDisplay. +/// +/// \return Pointer to the shared connection +/// +//////////////////////////////////////////////////////////// +xcb_connection_t* OpenConnection(); + +//////////////////////////////////////////////////////////// +/// \brief Release a reference to the shared display +/// +/// \param Display to release /// //////////////////////////////////////////////////////////// void CloseDisplay(Display* display); +//////////////////////////////////////////////////////////// +/// \brief Release a reference to the shared display +/// +/// \param Connection of display to release +/// +//////////////////////////////////////////////////////////// +void CloseConnection(xcb_connection_t* connection); + +//////////////////////////////////////////////////////////// +/// \brief Get screen of a display by index (equivalent to XScreenOfDisplay) +/// +/// \param The index of the screen +/// +/// \return Pointer to the screen +/// +//////////////////////////////////////////////////////////// +xcb_screen_t* XCBScreenOfDisplay(xcb_connection_t* connection, int screen_nbr); + } // namespace priv } // namespace sf diff --git a/src/SFML/Window/Unix/GlxContext.cpp b/src/SFML/Window/Unix/GlxContext.cpp index eac6099e2..b346753bc 100644 --- a/src/SFML/Window/Unix/GlxContext.cpp +++ b/src/SFML/Window/Unix/GlxContext.cpp @@ -44,18 +44,22 @@ m_ownsWindow(true) { // Open a connection with the X server m_display = OpenDisplay(); + m_connection = XGetXCBConnection(m_display); // Create a dummy window (disabled and hidden) - int screen = DefaultScreen(m_display); - m_window = XCreateWindow(m_display, - RootWindow(m_display, screen), - 0, 0, - 1, 1, - 0, - DefaultDepth(m_display, screen), - InputOutput, - DefaultVisual(m_display, screen), - 0, NULL); + xcb_screen_t* screen = XCBScreenOfDisplay(m_connection, DefaultScreen(m_display)); + m_window = xcb_generate_id(m_connection); + xcb_create_window( + m_connection, + screen->root_depth, + m_window, screen->root, + 0, 0, + 1, 1, + 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + screen->root_visual, + 0, NULL + ); // Create the context createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, ContextSettings()); @@ -71,6 +75,7 @@ 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); // Get the owner window and its device context m_window = static_cast< ::Window>(owner->getSystemHandle()); @@ -89,18 +94,22 @@ m_ownsWindow(true) { // Open a connection with the X server m_display = OpenDisplay(); + m_connection = XGetXCBConnection(m_display); // Create the hidden window - int screen = DefaultScreen(m_display); - m_window = XCreateWindow(m_display, - RootWindow(m_display, screen), - 0, 0, - width, height, - 0, - DefaultDepth(m_display, screen), - InputOutput, - DefaultVisual(m_display, screen), - 0, NULL); + xcb_screen_t* screen = XCBScreenOfDisplay(m_connection, DefaultScreen(m_display)); + m_window = xcb_generate_id(m_connection); + xcb_create_window( + m_connection, + screen->root_depth, + m_window, screen->root, + 0, 0, + width, height, + 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + screen->root_visual, + 0, NULL + ); // Create the context createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, settings); @@ -121,8 +130,8 @@ GlxContext::~GlxContext() // Destroy the window if we own it if (m_window && m_ownsWindow) { - XDestroyWindow(m_display, m_window); - XFlush(m_display); + xcb_destroy_window(m_connection, m_window); + xcb_flush(m_connection); } // Close the connection with the X server @@ -211,26 +220,88 @@ XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPe } } - //////////////////////////////////////////////////////////// void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings) { - XVisualInfo* visualInfo = NULL; - // Save the creation settings m_settings = settings; + // Get 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; + } + + // Setup the visual infos to match + XVisualInfo tpl; + tpl.depth = windowAttributes.depth; + tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); + tpl.screen = DefaultScreen(m_display); + + // Get all the visuals matching the template + int nbVisuals = 0; + XVisualInfo* visuals = XGetVisualInfo(m_display, VisualDepthMask | VisualIDMask | VisualScreenMask, &tpl, &nbVisuals); + if (!visuals || (nbVisuals == 0)) + { + if (visuals) + XFree(visuals); + err() << "There is no valid visual for the selected screen" << std::endl; + return; + } + + // Find the best visual + int bestScore = 0xFFFF; + XVisualInfo* bestVisual = NULL; + for (int i = 0; i < nbVisuals; ++i) + { + // Get the current visual attributes + int RGBA, doubleBuffer, red, green, blue, alpha, depth, stencil, multiSampling, samples; + glXGetConfig(m_display, &visuals[i], GLX_RGBA, &RGBA); + glXGetConfig(m_display, &visuals[i], GLX_DOUBLEBUFFER, &doubleBuffer); + glXGetConfig(m_display, &visuals[i], GLX_RED_SIZE, &red); + glXGetConfig(m_display, &visuals[i], GLX_GREEN_SIZE, &green); + glXGetConfig(m_display, &visuals[i], GLX_BLUE_SIZE, &blue); + glXGetConfig(m_display, &visuals[i], GLX_ALPHA_SIZE, &alpha); + glXGetConfig(m_display, &visuals[i], GLX_DEPTH_SIZE, &depth); + glXGetConfig(m_display, &visuals[i], GLX_STENCIL_SIZE, &stencil); + glXGetConfig(m_display, &visuals[i], GLX_SAMPLE_BUFFERS_ARB, &multiSampling); + glXGetConfig(m_display, &visuals[i], GLX_SAMPLES_ARB, &samples); + + // First check the mandatory parameters + if ((RGBA == 0) || (doubleBuffer == 0)) + continue; + + // Evaluate the current configuration + int color = red + green + blue + alpha; + int score = evaluateFormat(bitsPerPixel, m_settings, color, depth, stencil, multiSampling ? samples : 0); + + // Keep it if it's better than the current best + if (score < bestScore) + { + bestScore = score; + bestVisual = &visuals[i]; + } + } + + // Make sure that we have found a visual + if (!bestVisual) + { + err() << "Failed to find a suitable pixel format for the window -- cannot create OpenGL context" << std::endl; + return; + } + // Get the context to share display lists with GLXContext toShare = shared ? shared->m_context : NULL; // Create the OpenGL context -- first try context versions >= 3.0 if it is requested (they require special code) - if (m_settings.majorVersion >= 3) + while (!m_context && (m_settings.majorVersion >= 3)) { const GLubyte* name = reinterpret_cast("glXCreateContextAttribsARB"); PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = reinterpret_cast(glXGetProcAddress(name)); if (glXCreateContextAttribsARB) { - // Select a GLXFB config that matches the requested context settings int nbConfigs = 0; int fbAttributes[] = { @@ -250,43 +321,38 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co None }; GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), fbAttributes, &nbConfigs); + if (configs && nbConfigs) { - while (!m_context && (m_settings.majorVersion >= 3)) + // Create the context + int attributes[] = { - // Create the context - int attributes[] = - { - GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast(m_settings.majorVersion), - GLX_CONTEXT_MINOR_VERSION_ARB, static_cast(m_settings.minorVersion), - GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, - 0, 0 - }; - m_context = glXCreateContextAttribsARB(m_display, configs[0], toShare, true, attributes); + GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast(m_settings.majorVersion), + GLX_CONTEXT_MINOR_VERSION_ARB, static_cast(m_settings.minorVersion), + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, + 0, 0 + }; + m_context = glXCreateContextAttribsARB(m_display, configs[0], toShare, true, attributes); + } - if (m_context) - { - // Ok: retrieve the config's visual - visualInfo = glXGetVisualFromFBConfig(m_display, configs[0]); - } - else - { - // If we couldn't create the context, lower the version number and try again -- stop at 3.0 - // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care - if (m_settings.minorVersion > 0) - { - // If the minor version is not 0, we decrease it and try again - m_settings.minorVersion--; - } - else - { - // If the minor version is 0, we decrease the major version - m_settings.majorVersion--; - m_settings.minorVersion = 9; - } - } - } + if (configs) XFree(configs); + } + + // If we couldn't create the context, lower the version number and try again -- stop at 3.0 + // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care + if (!m_context) + { + if (m_settings.minorVersion > 0) + { + // If the minor version is not 0, we decrease it and try again + m_settings.minorVersion--; + } + else + { + // If the minor version is 0, we decrease the major version + m_settings.majorVersion--; + m_settings.minorVersion = 9; } } } @@ -298,23 +364,7 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co m_settings.majorVersion = 2; m_settings.minorVersion = 0; - // 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 visual - XVisualInfo tpl; - tpl.screen = DefaultScreen(m_display); - tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); - int nbVisuals = 0; - visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals); - - // Create the context, using the target window's visual - m_context = glXCreateContext(m_display, visualInfo, toShare, true); + m_context = glXCreateContext(m_display, bestVisual, toShare, true); if (!m_context) { err() << "Failed to create an OpenGL context for this window" << std::endl; @@ -324,16 +374,21 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co // 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); - glXGetConfig(m_display, visualInfo, GLX_SAMPLE_BUFFERS_ARB, &multiSampling); - glXGetConfig(m_display, visualInfo, GLX_SAMPLES_ARB, &samples); + glXGetConfig(m_display, bestVisual, GLX_DEPTH_SIZE, &depth); + glXGetConfig(m_display, bestVisual, GLX_STENCIL_SIZE, &stencil); + glXGetConfig(m_display, bestVisual, GLX_SAMPLE_BUFFERS_ARB, &multiSampling); + glXGetConfig(m_display, bestVisual, GLX_SAMPLES_ARB, &samples); m_settings.depthBits = static_cast(depth); m_settings.stencilBits = static_cast(stencil); m_settings.antialiasingLevel = multiSampling ? samples : 0; - // Free the visual info - XFree(visualInfo); + // Change the target window's colormap so that it matches the context's one + ::Window root = RootWindow(m_display, DefaultScreen(m_display)); + Colormap colorMap = XCreateColormap(m_display, root, bestVisual->visual, AllocNone); + XSetWindowColormap(m_display, m_window, colorMap); + + // Free the temporary visuals array + XFree(visuals); } } // namespace priv diff --git a/src/SFML/Window/Unix/GlxContext.hpp b/src/SFML/Window/Unix/GlxContext.hpp index 0b5982fb6..0e8bc402d 100644 --- a/src/SFML/Window/Unix/GlxContext.hpp +++ b/src/SFML/Window/Unix/GlxContext.hpp @@ -29,7 +29,7 @@ // Headers //////////////////////////////////////////////////////////// #include -#include +#include #include @@ -135,10 +135,11 @@ private: //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - ::Display* m_display; ///< Connection to the X server - ::Window m_window; ///< Window to which the context is attached - GLXContext m_context; ///< OpenGL context - bool m_ownsWindow; ///< Do we own the window associated to the context? + ::Display* m_display; ///< Connection to the X server + ::Window m_window; ///< Window to which the context is attached + xcb_connection_t* m_connection; ///< Pointer to the xcb connection + GLXContext m_context; ///< OpenGL context + bool m_ownsWindow; ///< Do we own the window associated to the context? }; } // namespace priv diff --git a/src/SFML/Window/Unix/InputImpl.cpp b/src/SFML/Window/Unix/InputImpl.cpp index 8ff76976f..68e396b64 100644 --- a/src/SFML/Window/Unix/InputImpl.cpp +++ b/src/SFML/Window/Unix/InputImpl.cpp @@ -28,8 +28,10 @@ #include #include #include -#include +#include +#include #include +#include namespace sf @@ -149,20 +151,20 @@ bool InputImpl::isKeyPressed(Keyboard::Key key) // Open a connection with the X server Display* display = OpenDisplay(); + xcb_connection_t* connection = XGetXCBConnection(display); // Convert to keycode KeyCode keycode = XKeysymToKeycode(display, keysym); if (keycode != 0) { // Get the whole keyboard state - char keys[32]; - XQueryKeymap(display, keys); + AutoPointer keymap = xcb_query_keymap_reply(connection, xcb_query_keymap(connection), NULL); // Close the connection with the X server CloseDisplay(display); // Check our keycode - return (keys[keycode / 8] & (1 << (keycode % 8))) != 0; + return (keymap->keys[keycode / 8] & (1 << (keycode % 8))) != 0; } else { @@ -186,29 +188,24 @@ bool InputImpl::isMouseButtonPressed(Mouse::Button button) { // Open a connection with the X server Display* display = OpenDisplay(); + xcb_connection_t* connection = XGetXCBConnection(display); - // we don't care about these but they are required - ::Window root, child; - int wx, wy; - int gx, gy; - - unsigned int buttons = 0; - XQueryPointer(display, DefaultRootWindow(display), &root, &child, &gx, &gy, &wx, &wy, &buttons); + // Get pointer mask + AutoPointer pointer = + xcb_query_pointer_reply(connection, xcb_query_pointer(connection, XDefaultRootWindow(display)), NULL); // Close the connection with the X server CloseDisplay(display); switch (button) { - case Mouse::Left: return buttons & Button1Mask; - case Mouse::Right: return buttons & Button3Mask; - case Mouse::Middle: return buttons & Button2Mask; - case Mouse::XButton1: return false; // not supported by X - case Mouse::XButton2: return false; // not supported by X + case Mouse::Left: return pointer->mask & XCB_BUTTON_MASK_1; + case Mouse::Right: return pointer->mask & XCB_BUTTON_MASK_3; + case Mouse::Middle: return pointer->mask & XCB_BUTTON_MASK_2; + case Mouse::XButton1: // not supported by X + case Mouse::XButton2: // not supported by X default: return false; } - - return false; } @@ -217,20 +214,15 @@ Vector2i InputImpl::getMousePosition() { // Open a connection with the X server Display* display = OpenDisplay(); + xcb_connection_t* connection = XGetXCBConnection(display); - // we don't care about these but they are required - ::Window root, child; - int x, y; - unsigned int buttons; - - int gx = 0; - int gy = 0; - XQueryPointer(display, DefaultRootWindow(display), &root, &child, &gx, &gy, &x, &y, &buttons); + AutoPointer pointer = + xcb_query_pointer_reply(connection, xcb_query_pointer(connection, XDefaultRootWindow(display)), NULL); // Close the connection with the X server CloseDisplay(display); - return Vector2i(gx, gy); + return Vector2i(pointer->root_x, pointer->root_y); } @@ -241,21 +233,15 @@ Vector2i InputImpl::getMousePosition(const Window& relativeTo) if (handle) { // Open a connection with the X server - Display* display = OpenDisplay(); + xcb_connection_t* connection = OpenConnection(); - // we don't care about these but they are required - ::Window root, child; - int gx, gy; - unsigned int buttons; - - int x = 0; - int y = 0; - XQueryPointer(display, handle, &root, &child, &gx, &gy, &x, &y, &buttons); + AutoPointer pointer = + xcb_query_pointer_reply(connection, xcb_query_pointer(connection, handle), NULL); // Close the connection with the X server - CloseDisplay(display); + CloseConnection(connection); - return Vector2i(x, y); + return Vector2i(pointer->win_x, pointer->win_y); } else { @@ -269,9 +255,10 @@ void InputImpl::setMousePosition(const Vector2i& position) { // Open a connection with the X server Display* display = OpenDisplay(); + xcb_connection_t* connection = XGetXCBConnection(display); - XWarpPointer(display, None, DefaultRootWindow(display), 0, 0, 0, 0, position.x, position.y); - XFlush(display); + xcb_warp_pointer(connection, None, XDefaultRootWindow(display), 0, 0, 0, 0, position.x, position.y); + xcb_flush(connection); // Close the connection with the X server CloseDisplay(display); @@ -282,17 +269,17 @@ void InputImpl::setMousePosition(const Vector2i& position) void InputImpl::setMousePosition(const Vector2i& position, const Window& relativeTo) { // Open a connection with the X server - Display* display = OpenDisplay(); + xcb_connection_t* connection = OpenConnection(); WindowHandle handle = relativeTo.getSystemHandle(); if (handle) { - XWarpPointer(display, None, handle, 0, 0, 0, 0, position.x, position.y); - XFlush(display); + xcb_warp_pointer(connection, None, handle, 0, 0, 0, 0, position.x, position.y); + xcb_flush(connection); } // Close the connection with the X server - CloseDisplay(display); + CloseConnection(connection); } diff --git a/src/SFML/Window/Unix/VideoModeImpl.cpp b/src/SFML/Window/Unix/VideoModeImpl.cpp index c7e620409..01ddf0363 100644 --- a/src/SFML/Window/Unix/VideoModeImpl.cpp +++ b/src/SFML/Window/Unix/VideoModeImpl.cpp @@ -28,8 +28,8 @@ #include #include #include -#include -#include +#include +#include #include @@ -44,63 +44,62 @@ std::vector VideoModeImpl::getFullscreenModes() // Open a connection with the X server Display* display = OpenDisplay(); + xcb_connection_t* connection = XGetXCBConnection(display); + if (display) { - // Retrieve the default screen number - int screen = DefaultScreen(display); + // Check if the XRandR extension is present + xcb_query_extension_cookie_t cookie = xcb_query_extension(connection, 5, "RANDR"); + + // Retrieve the default screen + xcb_screen_t* screen = XCBScreenOfDisplay(connection, DefaultScreen(display)); // Check if the XRandR extension is present - int version; - if (XQueryExtension(display, "RANDR", &version, &version, &version)) + xcb_query_extension_reply_t* randr_ext = xcb_query_extension_reply(connection, cookie, NULL); + if (randr_ext->present) { // Get the current configuration - XRRScreenConfiguration* config = XRRGetScreenInfo(display, RootWindow(display, screen)); - if (config) + xcb_generic_error_t* errors; + xcb_randr_get_screen_info_reply_t* config = xcb_randr_get_screen_info_reply( + connection, xcb_randr_get_screen_info(connection, screen->root), &errors); + if (! errors) { // Get the available screen sizes - int nbSizes; - XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes); - if (sizes && (nbSizes > 0)) + xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config); + if (sizes && (config->nSizes > 0)) { // Get the list of supported depths - int nbDepths = 0; - int* depths = XListDepths(display, screen, &nbDepths); - if (depths && (nbDepths > 0)) + xcb_depth_iterator_t iter = xcb_screen_allowed_depths_iterator(screen); + // Combine depths and sizes to fill the array of supported modes + for (; iter.rem; xcb_depth_next(&iter)) { - // Combine depths and sizes to fill the array of supported modes - for (int i = 0; i < nbDepths; ++i) + for (int j = 0; j < config->nSizes; ++j) { - for (int j = 0; j < nbSizes; ++j) - { - // Convert to VideoMode - VideoMode mode(sizes[j].width, sizes[j].height, depths[i]); + // Convert to VideoMode + VideoMode mode(sizes[j].width, sizes[j].height, iter.data->depth); - // Add it only if it is not already in the array - if (std::find(modes.begin(), modes.end(), mode) == modes.end()) - modes.push_back(mode); - } + // Add it only if it is not already in the array + if (std::find(modes.begin(), modes.end(), mode) == modes.end()) + modes.push_back(mode); } - - // Free the array of depths - XFree(depths); } } - - // Free the configuration instance - XRRFreeScreenConfigInfo(config); } else { // Failed to get the screen configuration err() << "Failed to retrieve the screen configuration while trying to get the supported video modes" << std::endl; } + // Free the configuration instance + free(errors); + free(config); } else { // XRandr extension is not supported: we cannot get the video modes err() << "Failed to use the XRandR extension while trying to get the supported video modes" << std::endl; } - + free(randr_ext); // Close the connection with the X server CloseDisplay(display); } @@ -121,37 +120,42 @@ VideoMode VideoModeImpl::getDesktopMode() // Open a connection with the X server Display* display = OpenDisplay(); + xcb_connection_t* connection = XGetXCBConnection(display); if (display) { - // Retrieve the default screen number - int screen = DefaultScreen(display); + xcb_query_extension_cookie_t cookie = xcb_query_extension(connection, 5, "RANDR"); + // Retrieve the default screen + xcb_screen_t* screen = XCBScreenOfDisplay(connection, DefaultScreen(display)); // Check if the XRandR extension is present - int version; - if (XQueryExtension(display, "RANDR", &version, &version, &version)) + xcb_query_extension_reply_t* randr_ext = xcb_query_extension_reply(connection, cookie, NULL); + if (randr_ext->present) { // Get the current configuration - XRRScreenConfiguration* config = XRRGetScreenInfo(display, RootWindow(display, screen)); - if (config) + xcb_generic_error_t* errors; + xcb_randr_get_screen_info_reply_t* config = + xcb_randr_get_screen_info_reply( + connection, xcb_randr_get_screen_info(connection, screen->root), &errors); + if (! errors) { // Get the current video mode - Rotation currentRotation; - int currentMode = XRRConfigCurrentConfiguration(config, ¤tRotation); + xcb_randr_rotation_t Rotation = (xcb_randr_rotation_t)config->rotation; + xcb_randr_mode_t currentMode = config->sizeID; // Get the available screen sizes - int nbSizes; - XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes); + int nbSizes = xcb_randr_get_screen_info_sizes_length(config); + xcb_randr_screen_size_t* sizes= xcb_randr_get_screen_info_sizes(config); if (sizes && (nbSizes > 0)) - desktopMode = VideoMode(sizes[currentMode].width, sizes[currentMode].height, DefaultDepth(display, screen)); - - // Free the configuration instance - XRRFreeScreenConfigInfo(config); + desktopMode = VideoMode(sizes[currentMode].width, sizes[currentMode].height, screen->root_depth); } else { // Failed to get the screen configuration err() << "Failed to retrieve the screen configuration while trying to get the desktop video modes" << std::endl; } + // Free the configuration instance + free(errors); + free(config); } else { @@ -159,6 +163,7 @@ VideoMode VideoModeImpl::getDesktopMode() err() << "Failed to use the XRandR extension while trying to get the desktop video modes" << std::endl; } + free(randr_ext); // Close the connection with the X server CloseDisplay(display); } diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 9e297576d..22ad33034 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -28,14 +28,15 @@ #include // important to be included first (conflict with None) #include #include +#include #include #include -#include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include #include @@ -104,6 +105,7 @@ m_useSizeHints(false) { // Open a connection with the X server m_display = OpenDisplay(); + XSetEventQueueOwner(m_display, XCBOwnsEventQueue); m_screen = DefaultScreen(m_display); // Save the window handle @@ -135,8 +137,14 @@ m_useSizeHints(false) { // Open a connection with the X server m_display = OpenDisplay(); - m_screen = DefaultScreen(m_display); - ::Window root = RootWindow(m_display, m_screen); + XSetEventQueueOwner(m_display, XCBOwnsEventQueue); + m_connection = XGetXCBConnection(m_display); + if (! m_connection) + { + err() << "Failed cast Display object to an XCB connection object" << std::endl; + return; + } + m_screen = DefaultScreen(m_display); // Compute position and size int left, top; @@ -162,22 +170,26 @@ m_useSizeHints(false) XVisualInfo visualInfo = ContextType::selectBestVisual(m_display, mode.bitsPerPixel, settings); // Define the window attributes - XSetWindowAttributes attributes; - attributes.override_redirect = fullscreen; - attributes.event_mask = eventMask; - attributes.colormap = XCreateColormap(m_display, root, visualInfo.visual, AllocNone); + const uint32_t value_list[] = {fullscreen, eventMask}; // Create the window - m_window = XCreateWindow(m_display, - root, - left, top, - width, height, - 0, - visualInfo.depth, - InputOutput, - visualInfo.visual, - CWEventMask | CWOverrideRedirect | CWColormap, &attributes); - if (!m_window) + m_window = xcb_generate_id(m_connection); + + xcb_void_cookie_t cookie = xcb_create_window_checked( + m_connection, + XCB_COPY_FROM_PARENT, + m_window, + RootWindow(m_display, m_screen), + left, top, + width, height, + 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + XCB_COPY_FROM_PARENT, + XCB_CW_EVENT_MASK | XCB_CW_OVERRIDE_REDIRECT, + value_list); + + ErrorPointer errptr(m_connection, cookie); + if(! errptr.isNull()) { err() << "Failed to create window" << std::endl; return; @@ -189,7 +201,7 @@ m_useSizeHints(false) // Set the window's style (tell the windows manager to change our window's decorations and functions according to the requested style) if (!fullscreen) { - Atom WMHintsAtom = XInternAtom(m_display, "_MOTIF_WM_HINTS", false); + xcb_atom_t WMHintsAtom = xcb_atom_get(m_connection, "_MOTIF_WM_HINTS"); if (WMHintsAtom) { static const unsigned long MWM_HINTS_FUNCTIONS = 1 << 0; @@ -212,11 +224,11 @@ m_useSizeHints(false) struct WMHints { - unsigned long flags; - unsigned long functions; - unsigned long decorations; - long inputMode; - unsigned long state; + uint32_t flags; + uint32_t functions; + uint32_t decorations; + int32_t inputMode; + uint32_t state; }; WMHints hints; @@ -241,19 +253,18 @@ m_useSizeHints(false) } const unsigned char* ptr = reinterpret_cast(&hints); - XChangeProperty(m_display, m_window, WMHintsAtom, WMHintsAtom, 32, PropModeReplace, ptr, 5); + xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE, m_window, + WMHintsAtom, WM_HINTS, 32, 5, ptr); } // This is a hack to force some windows managers to disable resizing if (!(style & Style::Resize)) { - m_useSizeHints = true; - XSizeHints* sizeHints = XAllocSizeHints(); - sizeHints->flags = PMinSize | PMaxSize; - sizeHints->min_width = sizeHints->max_width = width; - sizeHints->min_height = sizeHints->max_height = height; - XSetWMNormalHints(m_display, m_window, sizeHints); - XFree(sizeHints); + xcb_size_hints_t sizeHints; + sizeHints.flags = XCB_SIZE_HINT_P_MIN_SIZE | XCB_SIZE_HINT_P_MAX_SIZE; + sizeHints.min_width = sizeHints.max_width = width; + sizeHints.min_height = sizeHints.max_height = height; + xcb_set_wm_normal_hints(m_connection, m_window, &sizeHints); } } @@ -272,8 +283,8 @@ m_useSizeHints(false) // In fullscreen mode, we must grab keyboard and mouse inputs if (fullscreen) { - XGrabPointer(m_display, m_window, true, 0, GrabModeAsync, GrabModeAsync, m_window, None, CurrentTime); - XGrabKeyboard(m_display, m_window, true, GrabModeAsync, GrabModeAsync, CurrentTime); + xcb_grab_pointer(m_connection, True, m_window, 0, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, m_window, XCB_NONE, XCB_CURRENT_TIME); + xcb_grab_keyboard(m_connection, True, m_window, XCB_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); } } @@ -286,7 +297,7 @@ WindowImplX11::~WindowImplX11() // Destroy the cursor if (m_hiddenCursor) - XFreeCursor(m_display, m_hiddenCursor); + xcb_free_cursor(m_connection, m_hiddenCursor); // Destroy the input context if (m_inputContext) @@ -295,8 +306,8 @@ WindowImplX11::~WindowImplX11() // Destroy the window if (m_window && !m_isExternal) { - XDestroyWindow(m_display, m_window); - XFlush(m_display); + xcb_destroy_window(m_connection, m_window); + xcb_flush(m_connection); } // Close the input method @@ -321,10 +332,10 @@ WindowHandle WindowImplX11::getSystemHandle() const //////////////////////////////////////////////////////////// void WindowImplX11::processEvents() { - XEvent event; - while (XCheckIfEvent(m_display, &event, &checkEvent, reinterpret_cast(m_window))) + while(xcb_generic_event_t* event = xcb_poll_for_event(m_connection)) { processEvent(event); + free(event); } } @@ -332,80 +343,59 @@ void WindowImplX11::processEvents() //////////////////////////////////////////////////////////// Vector2i WindowImplX11::getPosition() const { - ::Window root, child; - int localX, localY, x, y; - unsigned int width, height, border, depth; - - XGetGeometry(m_display, m_window, &root, &localX, &localY, &width, &height, &border, &depth); - XTranslateCoordinates(m_display, m_window, root, localX, localY, &x, &y, &child); - - return Vector2i(x, y); + AutoPointer reply = + xcb_get_geometry_reply(m_connection, xcb_get_geometry(m_connection, m_window), NULL); + return Vector2i(reply->x, reply->y); } //////////////////////////////////////////////////////////// void WindowImplX11::setPosition(const Vector2i& position) { - XMoveWindow(m_display, m_window, position.x, position.y); - XFlush(m_display); + uint32_t values[] = {position.x, position.y}; + xcb_configure_window(m_connection, m_window, + XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, + values); + xcb_flush(m_connection); } //////////////////////////////////////////////////////////// Vector2u WindowImplX11::getSize() const { - XWindowAttributes attributes; - XGetWindowAttributes(m_display, m_window, &attributes); - return Vector2u(attributes.width, attributes.height); + AutoPointer reply = + xcb_get_geometry_reply(m_connection, xcb_get_geometry(m_connection, m_window), NULL); + return Vector2u(reply->width, reply->height); } //////////////////////////////////////////////////////////// void WindowImplX11::setSize(const Vector2u& size) { - // If we used size hint to fix the size of the window, we must update them - if (m_useSizeHints) - { - XSizeHints* sizeHints = XAllocSizeHints(); - sizeHints->flags = PMinSize | PMaxSize; - sizeHints->min_width = sizeHints->max_width = size.x; - sizeHints->min_height = sizeHints->max_height = size.y; - XSetWMNormalHints(m_display, m_window, sizeHints); - XFree(sizeHints); - } - - XResizeWindow(m_display, m_window, size.x, size.y); - XFlush(m_display); + uint32_t values[] = {size.x, size.y}; + xcb_configure_window(m_connection, m_window, + XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, + values); + xcb_flush(m_connection); } //////////////////////////////////////////////////////////// void WindowImplX11::setTitle(const String& title) { - // Bare X11 has no Unicode window title support. - // There is however an option to tell the window manager your Unicode title via hints. - - // Convert to UTF-8 encoding. - std::basic_string utf8Title; - Utf32::toUtf8(title.begin(), title.end(), std::back_inserter(utf8Title)); - - // Set the _NET_WM_NAME atom, which specifies a UTF-8 encoded window title. - Atom wmName = XInternAtom(m_display, "_NET_WM_NAME", False); - Atom useUtf8 = XInternAtom(m_display, "UTF8_STRING", False); - XChangeProperty(m_display, m_window, wmName, useUtf8, 8, - PropModeReplace, utf8Title.c_str(), utf8Title.size()); - - // Set the non-Unicode title as a fallback for window managers who don't support _NET_WM_NAME. - XStoreName(m_display, m_window, title.toAnsiString().c_str()); + const char* c_title = title.c_str(); + xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE, m_window, + WM_NAME, STRING, + 8, title.length(), c_title); + xcb_flush(m_connection); } //////////////////////////////////////////////////////////// void WindowImplX11::setIcon(unsigned int width, unsigned int height, const Uint8* pixels) { - // X11 wants BGRA pixels: swap red and blue channels - // Note: this memory will be freed by XDestroyImage - Uint8* iconPixels = static_cast(std::malloc(width * height * 4)); + // X11 wants BGRA pixels : swap red and blue channels + Uint8 iconPixels[width * height * 4]; for (std::size_t i = 0; i < width * height; ++i) { iconPixels[i * 4 + 0] = pixels[i * 4 + 2]; @@ -415,20 +405,25 @@ void WindowImplX11::setIcon(unsigned int width, unsigned int height, const Uint8 } // Create the icon pixmap - Visual* defVisual = DefaultVisual(m_display, m_screen); - unsigned int defDepth = DefaultDepth(m_display, m_screen); - XImage* iconImage = XCreateImage(m_display, defVisual, defDepth, ZPixmap, 0, (char*)iconPixels, width, height, 32, 0); - if (!iconImage) + uint8_t defDepth = DefaultDepth(m_display, m_screen); + + xcb_pixmap_t iconPixmap = xcb_generate_id(m_connection); + xcb_create_pixmap(m_connection, defDepth, iconPixmap, RootWindow(m_display, m_screen), + width, height); + + xcb_gcontext_t iconGC = xcb_generate_id(m_connection); + xcb_create_gc(m_connection, iconGC, iconPixmap, 0, NULL); + xcb_void_cookie_t cookie = xcb_put_image_checked( + m_connection, XCB_IMAGE_FORMAT_Z_PIXMAP, iconPixmap, iconGC, + width, height, 0, 0, 0, defDepth, sizeof(iconPixels), iconPixels); + xcb_free_gc(m_connection, iconGC); + + ErrorPointer errptr(m_connection, cookie); + if (! errptr.isNull()) { - err() << "Failed to set the window's icon" << std::endl; + err() << "Failed to set the window's icon: Error code " << (int)errptr->error_code << std::endl; return; } - Pixmap iconPixmap = XCreatePixmap(m_display, RootWindow(m_display, m_screen), width, height, defDepth); - XGCValues values; - GC iconGC = XCreateGC(m_display, iconPixmap, 0, &values); - XPutImage(m_display, iconPixmap, iconGC, iconImage, 0, 0, 0, 0, width, height); - XFreeGC(m_display, iconGC); - XDestroyImage(iconImage); // Create the mask pixmap (must have 1 bit depth) std::size_t pitch = (width + 7) / 8; @@ -447,17 +442,16 @@ void WindowImplX11::setIcon(unsigned int width, unsigned int height, const Uint8 } } } - Pixmap maskPixmap = XCreatePixmapFromBitmapData(m_display, m_window, (char*)&maskPixels[0], width, height, 1, 0, 1); + xcb_pixmap_t maskPixmap = xcb_create_pixmap_from_bitmap_data(m_connection, m_window, (Uint8*)&maskPixels[0], width, height, 1, 0, 1, NULL); // Send our new icon to the window through the WMHints - XWMHints* hints = XAllocWMHints(); - hints->flags = IconPixmapHint | IconMaskHint; - hints->icon_pixmap = iconPixmap; - hints->icon_mask = maskPixmap; - XSetWMHints(m_display, m_window, hints); - XFree(hints); + xcb_wm_hints_t hints; + hints.flags = XCB_WM_HINT_ICON_PIXMAP | XCB_WM_HINT_ICON_MASK; + hints.icon_pixmap = iconPixmap; + hints.icon_mask = maskPixmap; + xcb_set_wm_hints(m_connection, m_window, &hints); - XFlush(m_display); + xcb_flush(m_connection); } @@ -465,19 +459,20 @@ void WindowImplX11::setIcon(unsigned int width, unsigned int height, const Uint8 void WindowImplX11::setVisible(bool visible) { if (visible) - XMapWindow(m_display, m_window); + xcb_map_window(m_connection, m_window); else - XUnmapWindow(m_display, m_window); + xcb_unmap_window(m_connection, m_window); - XFlush(m_display); + xcb_flush(m_connection); } //////////////////////////////////////////////////////////// void WindowImplX11::setMouseCursorVisible(bool visible) { - XDefineCursor(m_display, m_window, visible ? None : m_hiddenCursor); - XFlush(m_display); + const uint32_t values = visible ? XCB_NONE : m_hiddenCursor; + xcb_change_window_attributes(m_connection, m_window, XCB_CW_CURSOR, &values); + xcb_flush(m_connection); } @@ -553,29 +548,37 @@ bool WindowImplX11::hasFocus() const void WindowImplX11::switchToFullscreen(const VideoMode& mode) { // Check if the XRandR extension is present - int version; - if (XQueryExtension(m_display, "RANDR", &version, &version, &version)) + xcb_query_extension_reply_t* randr_ext = + xcb_query_extension_reply(m_connection, xcb_query_extension(m_connection, 5, "RANDR"), NULL); + if (randr_ext->present) { + xcb_screen_t* screen = XCBScreenOfDisplay(m_connection, m_screen); // Get the current configuration - XRRScreenConfiguration* config = XRRGetScreenInfo(m_display, RootWindow(m_display, m_screen)); - if (config) + xcb_generic_error_t* errors; + xcb_randr_get_screen_info_reply_t* config = + xcb_randr_get_screen_info_reply(m_connection, + xcb_randr_get_screen_info(m_connection, screen->root), + &errors); + if (! errors) { - // Get the current rotation - Rotation currentRotation; - m_oldVideoMode = XRRConfigCurrentConfiguration(config, ¤tRotation); + // Save the current video mode before we switch to fullscreen + m_oldVideoMode = config->sizeID; // Get the available screen sizes - int nbSizes; - XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes); - if (sizes && (nbSizes > 0)) + xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config); + if (sizes && (config->nSizes > 0)) { // Search a matching size - for (int i = 0; i < nbSizes; ++i) + for (int i = 0; i < config->nSizes; ++i) { if ((sizes[i].width == static_cast(mode.width)) && (sizes[i].height == static_cast(mode.height))) { // Switch to fullscreen mode - XRRSetScreenConfig(m_display, config, RootWindow(m_display, m_screen), i, currentRotation, CurrentTime); + xcb_randr_set_screen_config(m_connection, + screen->root, + config->timestamp, + config->config_timestamp, + i, config->rotation, config->rate); // Set "this" as the current fullscreen window fullscreenWindow = this; @@ -583,30 +586,36 @@ void WindowImplX11::switchToFullscreen(const VideoMode& mode) } } } - - // Free the configuration instance - XRRFreeScreenConfigInfo(config); } else { // Failed to get the screen configuration err() << "Failed to get the current screen configuration for fullscreen mode, switching to window mode" << std::endl; } + free(errors); + free(config); } else { // XRandr extension is not supported: we cannot use fullscreen mode err() << "Fullscreen is not supported, switching to window mode" << std::endl; } + free(randr_ext); } //////////////////////////////////////////////////////////// void WindowImplX11::initialize() { + // Make sure the "last key release" is initialized with invalid values + m_lastKeyReleaseEvent.response_type = -1; + m_lastKeyReleaseEvent.detail = 0; + m_lastKeyReleaseEvent.time = 0; + // Get the atom defining the close event - m_atomClose = XInternAtom(m_display, "WM_DELETE_WINDOW", false); - XSetWMProtocols(m_display, m_window, &m_atomClose, 1); + m_atomClose = xcb_atom_get(m_connection, "WM_DELETE_WINDOW"); + xcb_atom_t wmprotocolsAtom = xcb_atom_get(m_connection, "WM_PROTOCOLS"); + xcb_set_wm_protocols(m_connection, wmprotocolsAtom, m_window, 1, &m_atomClose); // Create the input context m_inputMethod = XOpenIM(m_display, NULL, NULL, NULL); @@ -626,15 +635,15 @@ void WindowImplX11::initialize() err() << "Failed to create input context for window -- TextEntered event won't be able to return unicode" << std::endl; // Show the window - XMapWindow(m_display, m_window); - XFlush(m_display); + xcb_map_window(m_connection, m_window); + xcb_flush(m_connection); // Create the hidden cursor createHiddenCursor(); // Flush the commands queue - XFlush(m_display); - + xcb_flush(m_connection); + // Add this window to the global list of windows (required for focus request) allWindows.push_back(this); } @@ -643,20 +652,19 @@ void WindowImplX11::initialize() //////////////////////////////////////////////////////////// void WindowImplX11::createHiddenCursor() { + xcb_pixmap_t cursorPixmap = xcb_generate_id(m_connection); + m_hiddenCursor = xcb_generate_id(m_connection); // Create the cursor's pixmap (1x1 pixels) - Pixmap cursorPixmap = XCreatePixmap(m_display, m_window, 1, 1, 1); - GC graphicsContext = XCreateGC(m_display, cursorPixmap, 0, NULL); - XDrawPoint(m_display, cursorPixmap, graphicsContext, 0, 0); - XFreeGC(m_display, graphicsContext); + xcb_create_pixmap(m_connection, 1, cursorPixmap, m_window, 1, 1); // Create the cursor, using the pixmap as both the shape and the mask of the cursor - XColor color; - color.flags = DoRed | DoGreen | DoBlue; - color.red = color.blue = color.green = 0; - m_hiddenCursor = XCreatePixmapCursor(m_display, cursorPixmap, cursorPixmap, &color, &color, 0, 0); + xcb_create_cursor(m_connection, m_hiddenCursor, cursorPixmap, cursorPixmap, + 0, 0, 0, // Fore color + 0, 0, 0, // Back color + 0, 0); // We don't need the pixmap any longer, free it - XFreePixmap(m_display, cursorPixmap); + xcb_free_pixmap(m_connection, cursorPixmap); } @@ -666,20 +674,27 @@ void WindowImplX11::cleanup() // Restore the previous video mode (in case we were running in fullscreen) if (fullscreenWindow == this) { - // Get current screen info - XRRScreenConfiguration* config = XRRGetScreenInfo(m_display, RootWindow(m_display, m_screen)); - if (config) - { - // Get the current rotation - Rotation currentRotation; - XRRConfigCurrentConfiguration(config, ¤tRotation); + // Retrieve the default screen + xcb_screen_t* screen = XCBScreenOfDisplay(m_connection, m_screen); + // Get current screen info + xcb_generic_error_t* errors; + xcb_randr_get_screen_info_reply_t* config = xcb_randr_get_screen_info_reply( + m_connection, xcb_randr_get_screen_info(m_connection, screen->root), &errors); + if (! errors) + { // Reset the video mode - XRRSetScreenConfig(m_display, config, RootWindow(m_display, m_screen), m_oldVideoMode, currentRotation, CurrentTime); + xcb_randr_set_screen_config(m_connection, + screen->root, + CurrentTime, + config->config_timestamp, + m_oldVideoMode, + config->rotation, config->rate); // Free the configuration instance - XRRFreeScreenConfigInfo(config); + free(config); } + free(errors); // Reset the fullscreen window fullscreenWindow = NULL; @@ -691,7 +706,7 @@ void WindowImplX11::cleanup() //////////////////////////////////////////////////////////// -bool WindowImplX11::processEvent(XEvent windowEvent) +bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) { // This function implements a workaround to properly discard // repeated key events when necessary. The problem is that the @@ -702,26 +717,34 @@ bool WindowImplX11::processEvent(XEvent windowEvent) // - Discard both duplicated KeyPress and KeyRelease events when KeyRepeatEnabled is false // Detect repeated key events - // (code shamelessly taken from SDL) - if (windowEvent.type == KeyRelease) + if ((windowEvent->response_type == XCB_KEY_PRESS) || + (windowEvent->response_type == XCB_KEY_RELEASE)) { - // Check if there's a matching KeyPress event in the queue - XEvent nextEvent; - if (XPending(m_display)) + xcb_key_press_event_t* press = reinterpret_cast(windowEvent); + if (press->detail < 256) { - // Grab it but don't remove it from the queue, it still needs to be processed :) - XPeekEvent(m_display, &nextEvent); - if (nextEvent.type == KeyPress) - { - // Check if it is a duplicated event (same timestamp as the KeyRelease event) - if ((nextEvent.xkey.keycode == windowEvent.xkey.keycode) && - (nextEvent.xkey.time - windowEvent.xkey.time < 2)) - { - // If we don't want repeated events, remove the next KeyPress from the queue - if (!m_keyRepeat) - XNextEvent(m_display, &nextEvent); + // To detect if it is a repeated key event, we check the current state of the key. + // - If the state is "down", KeyReleased events must obviously be discarded. + // - KeyPress events are a little bit harder to handle: they depend on the EnableKeyRepeat state, + // and we need to properly forward the first one. + xcb_query_keymap_cookie_t cookie = xcb_query_keymap(m_connection); + AutoPointer keymap = xcb_query_keymap_reply(m_connection, + cookie, NULL); - // This KeyRelease is a repeated event and we don't want it + if (keymap->keys[press->detail / 8] & (1 << (press->detail % 8))) + { + // KeyRelease event + key down = repeated event --> discard + if (windowEvent->response_type == XCB_KEY_RELEASE) + { + m_lastKeyReleaseEvent = *press; + return false; + } + + // KeyPress event + key repeat disabled + matching KeyRelease event = repeated event --> discard + if ((windowEvent->response_type == XCB_KEY_PRESS) && !m_keyRepeat && + (m_lastKeyReleaseEvent.detail == press->detail) && + (m_lastKeyReleaseEvent.time == press->time)) + { return false; } } @@ -729,10 +752,10 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } // Convert the X11 event to a sf::Event - switch (windowEvent.type) + switch (windowEvent->response_type & ~0x80) { // Destroy event - case DestroyNotify: + case XCB_DESTROY_NOTIFY: { // The window is about to be destroyed: we must cleanup resources cleanup(); @@ -740,7 +763,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } // Gain focus event - case FocusIn: + case XCB_FOCUS_IN: { // Update the input context if (m_inputContext) @@ -763,7 +786,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } // Lost focus event - case FocusOut: + case XCB_FOCUS_OUT: { // Update the input context if (m_inputContext) @@ -776,27 +799,22 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } // Resize event - case ConfigureNotify: + case XCB_CONFIGURE_NOTIFY: { - // ConfigureNotify can be triggered for other reasons, check if the size has actually changed - if ((windowEvent.xconfigure.width != m_previousSize.x) || (windowEvent.xconfigure.height != m_previousSize.y)) - { - Event event; - event.type = Event::Resized; - event.size.width = windowEvent.xconfigure.width; - event.size.height = windowEvent.xconfigure.height; - pushEvent(event); - - m_previousSize.x = windowEvent.xconfigure.width; - m_previousSize.y = windowEvent.xconfigure.height; - } + xcb_configure_notify_event_t* e = reinterpret_cast(windowEvent); + Event event; + event.type = Event::Resized; + event.size.width = e->width; + event.size.height = e->height; + pushEvent(event); break; } // Close event - case ClientMessage: + case XCB_CLIENT_MESSAGE: { - if ((windowEvent.xclient.format == 32) && (windowEvent.xclient.data.l[0]) == static_cast(m_atomClose)) + xcb_client_message_event_t* e = reinterpret_cast(windowEvent); + if ((e->format == 32) && (e->data.data32[0]) == static_cast(m_atomClose)) { Event event; event.type = Event::Closed; @@ -806,34 +824,45 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } // Key down event - case KeyPress: + case XCB_KEY_PRESS: { + xcb_key_press_event_t* e = reinterpret_cast(windowEvent); // 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); + + // There is no xcb equivalent of XLookupString, so the xcb event + // has to be converted to an XEvent + XEvent fake_event; + fake_event.type = KeyPress; + fake_event.xany.display = m_display; + fake_event.xany.window = e->event; + fake_event.xkey.state = e->state; + fake_event.xkey.keycode = e->detail; + + XLookupString(&fake_event.xkey, buffer, sizeof(buffer), &symbol, &keyboard); // 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.alt = windowEvent.xkey.state & Mod1Mask; - event.key.control = windowEvent.xkey.state & ControlMask; - event.key.shift = windowEvent.xkey.state & ShiftMask; - event.key.system = windowEvent.xkey.state & Mod4Mask; + event.key.alt = e->state & XCB_MOD_MASK_1; + event.key.control = e->state & XCB_MOD_MASK_CONTROL; + event.key.shift = e->state & XCB_MOD_MASK_SHIFT; + event.key.system = e->state & XCB_MOD_MASK_4; pushEvent(event); // Generate a TextEntered event - if (!XFilterEvent(&windowEvent, None)) + if (!XFilterEvent(&fake_event, None)) { #ifdef X_HAVE_UTF8_STRING if (m_inputContext) { Status status; Uint8 keyBuffer[16]; - int length = Xutf8LookupString(m_inputContext, &windowEvent.xkey, reinterpret_cast(keyBuffer), sizeof(keyBuffer), NULL, &status); + int length = Xutf8LookupString(m_inputContext, &fake_event.xkey, reinterpret_cast(keyBuffer), sizeof(keyBuffer), NULL, &status); if (length > 0) { Uint32 unicode = 0; @@ -852,7 +881,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) { static XComposeStatus status; char keyBuffer[16]; - if (XLookupString(&windowEvent.xkey, keyBuffer, sizeof(keyBuffer), NULL, &status)) + if (XLookupString(&fake_event.xkey, keyBuffer, sizeof(keyBuffer), NULL, &status)) { Event textEvent; textEvent.type = Event::TextEntered; @@ -868,41 +897,53 @@ bool WindowImplX11::processEvent(XEvent windowEvent) // Key up event case KeyRelease: { + xcb_key_release_event_t* e = reinterpret_cast(windowEvent); // Get the keysym of the key that has been pressed char buffer[32]; KeySym symbol; - XLookupString(&windowEvent.xkey, buffer, 32, &symbol, NULL); + + // There is no xcb equivalent of XLookupString, so the xcb event + // has to be converted to an XEvent + XKeyEvent fake_event; + fake_event.display = m_display; + fake_event.state = e->state; + fake_event.keycode = e->detail; + XLookupString(&fake_event, buffer, 32, &symbol, NULL); // Fill the event parameters Event event; event.type = Event::KeyReleased; event.key.code = keysymToSF(symbol); - event.key.alt = windowEvent.xkey.state & Mod1Mask; - event.key.control = windowEvent.xkey.state & ControlMask; - event.key.shift = windowEvent.xkey.state & ShiftMask; - event.key.system = windowEvent.xkey.state & Mod4Mask; + event.key.alt = e->state & XCB_MOD_MASK_1; + event.key.control = e->state & XCB_MOD_MASK_CONTROL; + event.key.shift = e->state & XCB_MOD_MASK_SHIFT; + event.key.system = e->state & XCB_MOD_MASK_4; pushEvent(event); break; } // Mouse button pressed - case ButtonPress: + case XCB_BUTTON_PRESS: { - unsigned int button = windowEvent.xbutton.button; - if ((button == Button1) || (button == Button2) || (button == Button3) || (button == 8) || (button == 9)) + xcb_button_press_event_t* e = reinterpret_cast(windowEvent); + + // XXX: Why button 8 and 9? + xcb_button_t button = e->detail; + if ((button == XCB_BUTTON_INDEX_1) || (button == XCB_BUTTON_INDEX_2) + || (button == XCB_BUTTON_INDEX_3) || (button == 8) || (button == 9)) { Event event; event.type = Event::MouseButtonPressed; - event.mouseButton.x = windowEvent.xbutton.x; - event.mouseButton.y = windowEvent.xbutton.y; - switch (button) + event.mouseButton.x = e->event_x; + event.mouseButton.y = e->event_y; + switch(button) { - case Button1: event.mouseButton.button = Mouse::Left; break; - case Button2: event.mouseButton.button = Mouse::Middle; break; - case Button3: event.mouseButton.button = Mouse::Right; break; - case 8: event.mouseButton.button = Mouse::XButton1; break; - case 9: event.mouseButton.button = Mouse::XButton2; break; + case XCB_BUTTON_INDEX_1: event.mouseButton.button = Mouse::Left; break; + case XCB_BUTTON_INDEX_2: event.mouseButton.button = Mouse::Middle; break; + case XCB_BUTTON_INDEX_3: event.mouseButton.button = Mouse::Right; break; + case 8: event.mouseButton.button = Mouse::XButton1; break; + case 9: event.mouseButton.button = Mouse::XButton2; break; } pushEvent(event); } @@ -910,50 +951,54 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } // Mouse button released - case ButtonRelease: + case XCB_BUTTON_RELEASE: { - unsigned int button = windowEvent.xbutton.button; - if ((button == Button1) || (button == Button2) || (button == Button3) || (button == 8) || (button == 9)) + xcb_button_release_event_t* e = reinterpret_cast(windowEvent); + + xcb_button_t button = e->detail; + if ((button == XCB_BUTTON_INDEX_1) || (button == XCB_BUTTON_INDEX_2) + || (button == XCB_BUTTON_INDEX_3) || (button == 8) || (button == 9)) { Event event; - event.type = Event::MouseButtonReleased; - event.mouseButton.x = windowEvent.xbutton.x; - event.mouseButton.y = windowEvent.xbutton.y; - switch (button) + event.type = Event::MouseButtonPressed; + event.mouseButton.x = e->event_x; + event.mouseButton.y = e->event_y; + switch(button) { - case Button1: event.mouseButton.button = Mouse::Left; break; - case Button2: event.mouseButton.button = Mouse::Middle; break; - case Button3: event.mouseButton.button = Mouse::Right; break; - case 8: event.mouseButton.button = Mouse::XButton1; break; - case 9: event.mouseButton.button = Mouse::XButton2; break; + case XCB_BUTTON_INDEX_1: event.mouseButton.button = Mouse::Left; break; + case XCB_BUTTON_INDEX_2: event.mouseButton.button = Mouse::Middle; break; + case XCB_BUTTON_INDEX_3: event.mouseButton.button = Mouse::Right; break; + case 8: event.mouseButton.button = Mouse::XButton1; break; + case 9: event.mouseButton.button = Mouse::XButton2; break; } pushEvent(event); } - else if ((button == Button4) || (button == Button5)) + else if ((button == XCB_BUTTON_INDEX_4) || (button == XCB_BUTTON_INDEX_5)) { Event event; event.type = Event::MouseWheelMoved; - event.mouseWheel.delta = windowEvent.xbutton.button == Button4 ? 1 : -1; - event.mouseWheel.x = windowEvent.xbutton.x; - event.mouseWheel.y = windowEvent.xbutton.y; + event.mouseWheel.delta = button == XCB_BUTTON_INDEX_4 ? 1 : -1; + event.mouseWheel.x = e->event_x; + event.mouseWheel.y = e->event_y; pushEvent(event); } break; } // Mouse moved - case MotionNotify: + case XCB_MOTION_NOTIFY: { + xcb_motion_notify_event_t* e = reinterpret_cast(windowEvent); Event event; event.type = Event::MouseMoved; - event.mouseMove.x = windowEvent.xmotion.x; - event.mouseMove.y = windowEvent.xmotion.y; + event.mouseMove.x = e->event_x; + event.mouseMove.y = e->event_y; pushEvent(event); break; } // Mouse entered - case EnterNotify: + case XCB_ENTER_NOTIFY: { if (windowEvent.xcrossing.mode == NotifyNormal) { @@ -965,7 +1010,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) } // Mouse left - case LeaveNotify: + case XCB_LEAVE_NOTIFY: { if (windowEvent.xcrossing.mode == NotifyNormal) { @@ -989,7 +1034,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) //////////////////////////////////////////////////////////// -Keyboard::Key WindowImplX11::keysymToSF(KeySym symbol) +Keyboard::Key WindowImplX11::keysymToSF(xcb_keysym_t symbol) { // First convert to uppercase (to avoid dealing with two different keysyms for the same key) KeySym lower, key; diff --git a/src/SFML/Window/Unix/WindowImplX11.hpp b/src/SFML/Window/Unix/WindowImplX11.hpp index d824492c8..7882aa01c 100644 --- a/src/SFML/Window/Unix/WindowImplX11.hpp +++ b/src/SFML/Window/Unix/WindowImplX11.hpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include @@ -213,7 +213,7 @@ private: /// \return True if the event was processed, false if it was discarded /// //////////////////////////////////////////////////////////// - bool processEvent(XEvent windowEvent); + bool processEvent(xcb_generic_event_t *windowEvent); //////////////////////////////////////////////////////////// /// \brief Convert a X11 keysym to SFML key code @@ -223,23 +223,24 @@ private: /// \return Corresponding SFML key code /// //////////////////////////////////////////////////////////// - static Keyboard::Key keysymToSF(KeySym symbol); + static Keyboard::Key keysymToSF(xcb_keysym_t symbol); //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - ::Window m_window; ///< X11 structure defining our window - ::Display* m_display; ///< Pointer to the display - int m_screen; ///< Screen identifier - XIM m_inputMethod; ///< Input method linked to the X display - XIC m_inputContext; ///< Input context used to get Unicode input in our window - bool m_isExternal; ///< Tell whether the window has been created externally or by SFML - Atom m_atomClose; ///< Atom used to identify the close event - int m_oldVideoMode; ///< Video mode in use before we switch to fullscreen - Cursor m_hiddenCursor; ///< As X11 doesn't provide cursor hiding, we must create a transparent one - bool m_keyRepeat; ///< Is the KeyRepeat feature enabled? - Vector2i m_previousSize; ///< Previous size of the window, to find if a ConfigureNotify event is a resize event (could be a move event only) - bool m_useSizeHints; ///< Is the size of the window fixed with size hints? + ::Window m_window; ///< X11 structure defining our window + ::Display* m_display; ///< Pointer to the display + xcb_connection_t* m_connection; ///< Pointer to the xcb connection + int m_screen; ///< Screen identifier + XIM m_inputMethod; ///< Input method linked to the X display + XIC m_inputContext; ///< Input context used to get unicode input in our window + bool m_isExternal; ///< Tell whether the window has been created externally or by SFML + Atom m_atomClose; ///< Atom used to identify the close event + int m_oldVideoMode; ///< Video mode in use before we switch to fullscreen + Cursor m_hiddenCursor; ///< As X11 doesn't provide cursor hidding, we must create a transparent one + bool m_keyRepeat; ///< Is the KeyRepeat feature enabled? + Vector2i m_previousSize; ///< Previous size of the window, to find if a ConfigureNotify event is a resize event (could be a move event only) + bool m_useSizeHints; ///< Is the size of the window fixed with size hints? }; } // namespace priv