From b2b35d0a4398b67c805007ee0f1ff05e2b0740df Mon Sep 17 00:00:00 2001 From: binary1248 Date: Fri, 6 Mar 2015 16:11:56 +0100 Subject: [PATCH] Refactored Unix Window implementation. --- src/SFML/Window/CMakeLists.txt | 7 +- src/SFML/Window/Unix/Display.cpp | 17 + src/SFML/Window/Unix/Display.hpp | 27 +- src/SFML/Window/Unix/InputImpl.cpp | 21 +- src/SFML/Window/Unix/VideoModeImpl.cpp | 187 +++++----- src/SFML/Window/Unix/WindowImplX11.cpp | 457 ++++++++++++++++--------- 6 files changed, 456 insertions(+), 260 deletions(-) diff --git a/src/SFML/Window/CMakeLists.txt b/src/SFML/Window/CMakeLists.txt index 799d44941..88dff86c2 100644 --- a/src/SFML/Window/CMakeLists.txt +++ b/src/SFML/Window/CMakeLists.txt @@ -217,11 +217,10 @@ endif() # build the list of external libraries to link if(SFML_OS_WINDOWS) list(APPEND WINDOW_EXT_LIBS winmm gdi32) -elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD) +elseif(SFML_OS_LINUX) list(APPEND WINDOW_EXT_LIBS ${LIBXCB_LIBRARIES} ${UDEV_LIBRARIES}) - if(SFML_OS_FREEBSD) - list(APPEND WINDOW_EXT_LIBS usbhid) - endif() +elseif(SFML_OS_FREEBSD) + list(APPEND WINDOW_EXT_LIBS ${LIBXCB_LIBRARIES} usbhid) elseif(SFML_OS_MACOSX) list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework AppKit -framework IOKit -framework Carbon") elseif(SFML_OS_IOS) diff --git a/src/SFML/Window/Unix/Display.cpp b/src/SFML/Window/Unix/Display.cpp index d8f79aad1..969e01cc3 100644 --- a/src/SFML/Window/Unix/Display.cpp +++ b/src/SFML/Window/Unix/Display.cpp @@ -101,6 +101,23 @@ xcb_screen_t* XCBScreenOfDisplay(xcb_connection_t* connection, int screen_nbr) return NULL; } +//////////////////////////////////////////////////////////// +xcb_screen_t* XCBDefaultScreen(xcb_connection_t* connection) +{ + assert(connection == XGetXCBConnection(sharedDisplay)); + return XCBScreenOfDisplay(connection, XDefaultScreen(sharedDisplay)); +} + +//////////////////////////////////////////////////////////// +xcb_window_t XCBDefaultRootWindow(xcb_connection_t* connection) +{ + assert(connection == XGetXCBConnection(sharedDisplay)); + xcb_screen_t* screen = XCBScreenOfDisplay(connection, XDefaultScreen(sharedDisplay)); + if (screen) + return screen->root; + return 0; +} + } // namespace priv } // namespace sf diff --git a/src/SFML/Window/Unix/Display.hpp b/src/SFML/Window/Unix/Display.hpp index e179326cd..469f07201 100644 --- a/src/SFML/Window/Unix/Display.hpp +++ b/src/SFML/Window/Unix/Display.hpp @@ -60,7 +60,7 @@ xcb_connection_t* OpenConnection(); //////////////////////////////////////////////////////////// /// \brief Release a reference to the shared display /// -/// \param Display to release +/// \param display Display to release /// //////////////////////////////////////////////////////////// void CloseDisplay(Display* display); @@ -68,7 +68,7 @@ void CloseDisplay(Display* display); //////////////////////////////////////////////////////////// /// \brief Release a reference to the shared display /// -/// \param Connection of display to release +/// \param connection Connection of display to release /// //////////////////////////////////////////////////////////// void CloseConnection(xcb_connection_t* connection); @@ -76,13 +76,34 @@ void CloseConnection(xcb_connection_t* connection); //////////////////////////////////////////////////////////// /// \brief Get screen of a display by index (equivalent to XScreenOfDisplay) /// -/// \param The index of the screen +/// \param connection Connection of display +/// \param screen_nbr The index of the screen /// /// \return Pointer to the screen /// //////////////////////////////////////////////////////////// xcb_screen_t* XCBScreenOfDisplay(xcb_connection_t* connection, int screen_nbr); +//////////////////////////////////////////////////////////// +/// \brief Get default screen of a display (equivalent to XDefaultScreen) +/// +/// \param connection Connection of display +/// +/// \return Pointer to the default screen of the display +/// +//////////////////////////////////////////////////////////// +xcb_screen_t* XCBDefaultScreen(xcb_connection_t* connection); + +//////////////////////////////////////////////////////////// +/// \brief Get default root window of a display (equivalent to XDefaultRootWindow) +/// +/// \param connection Connection of display +/// +/// \return Root window of the display +/// +//////////////////////////////////////////////////////////// +xcb_window_t XCBDefaultRootWindow(xcb_connection_t* connection); + } // namespace priv } // namespace sf diff --git a/src/SFML/Window/Unix/InputImpl.cpp b/src/SFML/Window/Unix/InputImpl.cpp index 7e04e533b..8ac0925c1 100644 --- a/src/SFML/Window/Unix/InputImpl.cpp +++ b/src/SFML/Window/Unix/InputImpl.cpp @@ -189,16 +189,15 @@ void InputImpl::setVirtualKeyboardVisible(bool /*visible*/) bool InputImpl::isMouseButtonPressed(Mouse::Button button) { // Open a connection with the X server - Display* display = OpenDisplay(); - xcb_connection_t* connection = XGetXCBConnection(display); + xcb_connection_t* connection = OpenConnection(); // Get pointer mask - xcb_query_pointer_reply_t* pointer = xcb_query_pointer_reply(connection, xcb_query_pointer(connection, XDefaultRootWindow(display)), NULL); + xcb_query_pointer_reply_t* pointer = xcb_query_pointer_reply(connection, xcb_query_pointer(connection, XCBDefaultRootWindow(connection)), NULL); uint16_t mask = pointer->mask; free(pointer); // Close the connection with the X server - CloseDisplay(display); + CloseConnection(connection); switch (button) { @@ -216,13 +215,12 @@ bool InputImpl::isMouseButtonPressed(Mouse::Button button) Vector2i InputImpl::getMousePosition() { // Open a connection with the X server - Display* display = OpenDisplay(); - xcb_connection_t* connection = XGetXCBConnection(display); + xcb_connection_t* connection = OpenConnection(); - xcb_query_pointer_reply_t* pointer = xcb_query_pointer_reply(connection, xcb_query_pointer(connection, XDefaultRootWindow(display)), NULL); + xcb_query_pointer_reply_t* pointer = xcb_query_pointer_reply(connection, xcb_query_pointer(connection, XCBDefaultRootWindow(connection)), NULL); // Close the connection with the X server - CloseDisplay(display); + CloseConnection(connection); // Prepare result. Vector2i result(pointer->root_x, pointer->root_y); @@ -263,14 +261,13 @@ Vector2i InputImpl::getMousePosition(const Window& relativeTo) void InputImpl::setMousePosition(const Vector2i& position) { // Open a connection with the X server - Display* display = OpenDisplay(); - xcb_connection_t* connection = XGetXCBConnection(display); + xcb_connection_t* connection = OpenConnection(); - xcb_warp_pointer(connection, None, XDefaultRootWindow(display), 0, 0, 0, 0, position.x, position.y); + xcb_warp_pointer(connection, None, XCBDefaultRootWindow(connection), 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 918dfabc3..ce5bc1ea5 100644 --- a/src/SFML/Window/Unix/VideoModeImpl.cpp +++ b/src/SFML/Window/Unix/VideoModeImpl.cpp @@ -42,72 +42,80 @@ std::vector VideoModeImpl::getFullscreenModes() std::vector modes; // Open a connection with the X server - Display* display = OpenDisplay(); - xcb_connection_t* connection = XGetXCBConnection(display); + xcb_connection_t* connection = OpenConnection(); - if (display) + // Retrieve the default screen + xcb_screen_t* screen = XCBDefaultScreen(connection); + + // Check if the XRandR extension is present + static const std::string RANDR = "RANDR"; + xcb_query_extension_reply_t* randr_ext = xcb_query_extension_reply( + connection, + xcb_query_extension( + connection, + RANDR.size(), + RANDR.c_str() + ), + NULL + ); + + if (randr_ext->present) { - // Check if the XRandR extension is present - xcb_query_extension_cookie_t cookie = xcb_query_extension(connection, 5, "RANDR"); + // Get the current configuration + xcb_generic_error_t* error; + xcb_randr_get_screen_info_reply_t* config = xcb_randr_get_screen_info_reply( + connection, + xcb_randr_get_screen_info( + connection, + screen->root + ), + &error + ); - // Retrieve the default screen - xcb_screen_t* screen = XCBScreenOfDisplay(connection, DefaultScreen(display)); - - // Check if the XRandR extension is present - xcb_query_extension_reply_t* randr_ext = xcb_query_extension_reply(connection, cookie, NULL); - if (randr_ext->present) + if (!error) { - // Get the current configuration - 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 + xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config); + if (sizes && (config->nSizes > 0)) { - // Get the available screen sizes - xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config); - if (sizes && (config->nSizes > 0)) + // Get the list of supported depths + xcb_depth_iterator_t iter = xcb_screen_allowed_depths_iterator(screen); + // Combine depths and sizes to fill the array of supported modes + for (; iter.rem; xcb_depth_next(&iter)) { - // Get the list of supported depths - xcb_depth_iterator_t iter = xcb_screen_allowed_depths_iterator(screen); - // Combine depths and sizes to fill the array of supported modes - for (; iter.rem; xcb_depth_next(&iter)) + for (int j = 0; j < config->nSizes; ++j) { - for (int j = 0; j < config->nSizes; ++j) - { - // Convert to VideoMode - VideoMode mode(sizes[j].width, sizes[j].height, iter.data->depth); + // 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); } } } - 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; + // Failed to get the screen configuration + err() << "Failed to retrieve the screen configuration while trying to get the supported video modes" << std::endl; } - free(randr_ext); - // Close the connection with the X server - CloseDisplay(display); + + // Free the configuration instance + free(error); + free(config); } else { - // We couldn't connect to the X server - err() << "Failed to connect to the X server while trying to get the supported video modes" << std::endl; + // 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 + CloseConnection(connection); + return modes; } @@ -118,59 +126,68 @@ VideoMode VideoModeImpl::getDesktopMode() VideoMode desktopMode; // Open a connection with the X server - Display* display = OpenDisplay(); - xcb_connection_t* connection = XGetXCBConnection(display); - if (display) + xcb_connection_t* connection = OpenConnection(); + + // Retrieve the default screen + xcb_screen_t* screen = XCBDefaultScreen(connection); + + // Check if the XRandR extension is present + static const std::string RANDR = "RANDR"; + xcb_query_extension_reply_t* randr_ext = xcb_query_extension_reply( + connection, + xcb_query_extension( + connection, + RANDR.size(), + RANDR.c_str() + ), + NULL + ); + + if (randr_ext->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)); + // Get the current configuration + xcb_generic_error_t* error; + xcb_randr_get_screen_info_reply_t* config = xcb_randr_get_screen_info_reply( + connection, + xcb_randr_get_screen_info( + connection, + screen->root + ), + &error + ); - // Check if the XRandR extension is present - xcb_query_extension_reply_t* randr_ext = xcb_query_extension_reply(connection, cookie, NULL); - if (randr_ext->present) + if (!error) { - // Get the current configuration - 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 - xcb_randr_mode_t currentMode = config->sizeID; + // Get the current video mode + xcb_randr_mode_t currentMode = config->sizeID; - // Get the available screen sizes - int nbSizes = xcb_randr_get_screen_info_sizes_length(config); - 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, 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); + // Get the available screen sizes + 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, screen->root_depth); } else { - // XRandr extension is not supported: we cannot get the video modes - err() << "Failed to use the XRandR extension while trying to get the desktop video modes" << std::endl; + // Failed to get the screen configuration + err() << "Failed to retrieve the screen configuration while trying to get the desktop video modes" << std::endl; } - free(randr_ext); - // Close the connection with the X server - CloseDisplay(display); + // Free the configuration instance + free(error); + free(config); } else { - // We couldn't connect to the X server - err() << "Failed to connect to the X server while trying to get the desktop video modes" << std::endl; + // XRandr extension is not supported: we cannot get the video modes + err() << "Failed to use the XRandR extension while trying to get the desktop video modes" << std::endl; } + free(randr_ext); + + // Close the connection with the X server + CloseConnection(connection); + return desktopMode; } diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 33672e0e9..b4188842e 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include #include #include @@ -65,18 +67,22 @@ namespace EnterWindowMask | LeaveWindowMask; // Find the name of the current executable - void findExecutableName(char* buffer, std::size_t bufferSize) + std::string findExecutableName() { - //Default fallback name - const char* executableName = "sfml"; - std::size_t length = readlink("/proc/self/exe", buffer, bufferSize); - if ((length > 0) && (length < bufferSize)) - { - // Remove the path to keep the executable name only - buffer[length] = '\0'; - executableName = basename(buffer); + struct stat linkStat; + if (!lstat("/proc/self/exe", &linkStat)) { + std::vector buffer(0, linkStat.st_size + 1); + std::size_t length = readlink("/proc/self/exe", &buffer[0], buffer.size()); + if ((length > 0) && (length < buffer.size())) + { + // Remove the path to keep the executable name only + buffer[length] = '\0'; + return basename(&buffer[0]); + } } - std::memmove(buffer, executableName, std::strlen(executableName) + 1); + + //Default fallback name + return "sfml"; } } @@ -100,7 +106,6 @@ m_useSizeHints(false) { // Open a connection with the X server m_display = OpenDisplay(); - XSetEventQueueOwner(m_display, XCBOwnsEventQueue); m_connection = XGetXCBConnection(m_display); if (!m_connection) @@ -109,10 +114,8 @@ m_useSizeHints(false) return; } - // Get connection info. - const xcb_setup_t* setup = xcb_get_setup(m_connection); - xcb_screen_iterator_t screenIter = xcb_setup_roots_iterator(setup); - m_screen = screenIter.data; + m_screen = XCBDefaultScreen(m_connection); + XSetEventQueueOwner(m_display, XCBOwnsEventQueue); // Save the window handle m_window = handle; @@ -122,10 +125,12 @@ m_useSizeHints(false) // Make sure the window is listening to all the required events const uint32_t value_list[] = {static_cast(eventMask)}; - xcb_change_window_attributes(m_connection, - m_window, - XCB_CW_EVENT_MASK, - value_list); + xcb_change_window_attributes( + m_connection, + m_window, + XCB_CW_EVENT_MASK, + value_list + ); // Do some common initializations initialize(); @@ -148,32 +153,21 @@ m_useSizeHints(false) { // Open a connection with the X server m_display = OpenDisplay(); - 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; } - // Get connection info. - const xcb_setup_t* setup = xcb_get_setup(m_connection); - xcb_screen_iterator_t screenIter = xcb_setup_roots_iterator(setup); - m_screen = screenIter.data; + m_screen = XCBDefaultScreen(m_connection); + XSetEventQueueOwner(m_display, XCBOwnsEventQueue); // Compute position and size - int left, top; bool fullscreen = (style & Style::Fullscreen) != 0; - if (!fullscreen) - { - left = (m_screen->width_in_pixels - mode.width) / 2; - top = (m_screen->height_in_pixels - mode.height) / 2; - } - else - { - left = 0; - top = 0; - } + int left = fullscreen ? 0 : (m_screen->width_in_pixels - mode.width) / 2; + int top = fullscreen ? 0 : (m_screen->height_in_pixels - mode.height) / 2; int width = mode.width; int height = mode.height; @@ -187,20 +181,23 @@ m_useSizeHints(false) // Create the 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, - m_screen->root, - left, top, - width, height, - 0, - XCB_WINDOW_CLASS_INPUT_OUTPUT, - XCB_COPY_FROM_PARENT, - XCB_CW_EVENT_MASK | XCB_CW_OVERRIDE_REDIRECT, - value_list); + xcb_generic_error_t* errptr = xcb_request_check( + m_connection, + xcb_create_window_checked( + m_connection, + XCB_COPY_FROM_PARENT, + m_window, + m_screen->root, + left, top, + width, height, + 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + XCB_COPY_FROM_PARENT, + XCB_CW_EVENT_MASK | XCB_CW_OVERRIDE_REDIRECT, + value_list + ) + ); - xcb_generic_error_t* errptr = xcb_request_check(m_connection, cookie); bool createWindowFailed = (errptr != NULL); free(errptr); @@ -213,19 +210,18 @@ m_useSizeHints(false) // Set the window's name setTitle(title); - // Set the window's style (tell the windows manager to change our window's decorations and functions according to the requested style) + // Set the window's style (tell the window manager to change our window's decorations and functions according to the requested style) if (!fullscreen) { static const std::string MOTIF_WM_HINTS = "_MOTIF_WM_HINTS"; - xcb_intern_atom_cookie_t hintsAtomRequest = xcb_intern_atom( - m_connection, - 0, - MOTIF_WM_HINTS.size(), - MOTIF_WM_HINTS.c_str() - ); xcb_intern_atom_reply_t* hintsAtomReply = xcb_intern_atom_reply( m_connection, - hintsAtomRequest, + xcb_intern_atom( + m_connection, + 0, + MOTIF_WM_HINTS.size(), + MOTIF_WM_HINTS.c_str() + ), NULL ); @@ -279,9 +275,16 @@ m_useSizeHints(false) hints.functions |= MWM_FUNC_CLOSE; } - const unsigned char* ptr = reinterpret_cast(&hints); - xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE, m_window, - hintsAtomReply->atom, XCB_ATOM_WM_HINTS, 32, 5, ptr); + xcb_change_property( + m_connection, + XCB_PROP_MODE_REPLACE, + m_window, + hintsAtomReply->atom, + XCB_ATOM_WM_HINTS, + sizeof(hints.flags) * 8, + sizeof(hints) / sizeof(hints.flags), + reinterpret_cast(&hints) + ); free(hintsAtomReply); } @@ -299,9 +302,8 @@ m_useSizeHints(false) } // Set the window's WM class (this can be used by window managers) - char windowClass[512]; - findExecutableName(windowClass, sizeof(windowClass)); - xcb_icccm_set_wm_class_checked(m_connection, m_window, std::strlen(windowClass), windowClass); + std::string windowClass = findExecutableName(); + xcb_icccm_set_wm_class_checked(m_connection, m_window, windowClass.size(), windowClass.c_str()); // Do some common initializations initialize(); @@ -309,8 +311,26 @@ m_useSizeHints(false) // In fullscreen mode, we must grab keyboard and mouse inputs if (fullscreen) { - 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); + 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 + ); } } @@ -422,7 +442,6 @@ Vector2i WindowImplX11::getPosition() const { ::Window topLevelWindow = m_window; ::Window nextWindow = topLevelWindow; - xcb_query_tree_cookie_t treeCookie; xcb_query_tree_reply_t* treeReply = NULL; // Get "top level" window, i.e. the window with the root window as its parent. @@ -430,14 +449,19 @@ Vector2i WindowImplX11::getPosition() const { topLevelWindow = nextWindow; - treeCookie = xcb_query_tree(m_connection, topLevelWindow); - treeReply = xcb_query_tree_reply(m_connection, treeCookie, NULL); + treeReply = xcb_query_tree_reply(m_connection, xcb_query_tree(m_connection, topLevelWindow), NULL); nextWindow = treeReply->parent; free(treeReply); } - xcb_get_geometry_cookie_t geometryCookie = xcb_get_geometry(m_connection, topLevelWindow); - xcb_get_geometry_reply_t* geometryReply = xcb_get_geometry_reply(m_connection, geometryCookie, NULL); + xcb_get_geometry_reply_t* geometryReply = xcb_get_geometry_reply( + m_connection, + xcb_get_geometry( + m_connection, + topLevelWindow + ), + NULL + ); sf::Vector2i result(geometryReply->x, geometryReply->y); free(geometryReply); @@ -480,9 +504,12 @@ void WindowImplX11::setSize(const Vector2u& size) } uint32_t values[] = {size.x, size.y}; - xcb_configure_window(m_connection, m_window, - XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, - values); + xcb_configure_window( + m_connection, + m_window, + XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, + values + ); xcb_flush(m_connection); } @@ -497,9 +524,16 @@ void WindowImplX11::setTitle(const String& title) std::back_inserter( utf8String ) ); - xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE, m_window, - XCB_ATOM_WM_NAME, XCB_ATOM_STRING, - 8, utf8String.length(), utf8String.c_str()); + xcb_change_property( + m_connection, + XCB_PROP_MODE_REPLACE, + m_window, + XCB_ATOM_WM_NAME, + XCB_ATOM_STRING, + sizeof(std::basic_string::value_type) * 8, + utf8String.length(), + utf8String.c_str() + ); xcb_flush(m_connection); } @@ -519,17 +553,38 @@ void WindowImplX11::setIcon(unsigned int width, unsigned int height, const Uint8 // Create the icon pixmap xcb_pixmap_t iconPixmap = xcb_generate_id(m_connection); - xcb_create_pixmap(m_connection, m_screen->root_depth, iconPixmap, m_screen->root, - width, height); + xcb_create_pixmap( + m_connection, + m_screen->root_depth, + iconPixmap, + m_screen->root, + 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, m_screen->root_depth, sizeof(iconPixels), iconPixels); + + xcb_generic_error_t* errptr = xcb_request_check( + m_connection, + xcb_put_image_checked( + m_connection, + XCB_IMAGE_FORMAT_Z_PIXMAP, + iconPixmap, + iconGC, + width, + height, + 0, + 0, + 0, + m_screen->root_depth, + sizeof(iconPixels), + iconPixels + ) + ); + xcb_free_gc(m_connection, iconGC); - xcb_generic_error_t* errptr = xcb_request_check(m_connection, cookie); if (errptr) { err() << "Failed to set the window's icon: Error code " << static_cast(errptr->error_code) << std::endl; @@ -554,7 +609,18 @@ void WindowImplX11::setIcon(unsigned int width, unsigned int height, const Uint8 } } } - xcb_pixmap_t maskPixmap = xcb_create_pixmap_from_bitmap_data(m_connection, m_window, (Uint8*)&maskPixels[0], width, height, 1, 0, 1, NULL); + + xcb_pixmap_t maskPixmap = xcb_create_pixmap_from_bitmap_data( + m_connection, + m_window, + reinterpret_cast(&maskPixels[0]), + width, + height, + 1, + 0, + 1, + NULL + ); // Send our new icon to the window through the WMHints xcb_icccm_wm_hints_t hints; @@ -613,10 +679,14 @@ void WindowImplX11::requestFocus() // Check if window is viewable (not on other desktop, ...) // TODO: Check also if minimized - xcb_get_window_attributes_cookie_t attribCookie = xcb_get_window_attributes(m_connection, m_window); - xcb_get_window_attributes_reply_t* attributes = xcb_get_window_attributes_reply(m_connection, - attribCookie, - NULL); + xcb_get_window_attributes_reply_t* attributes = xcb_get_window_attributes_reply( + m_connection, + xcb_get_window_attributes( + m_connection, + m_window + ), + NULL + ); if (!attributes) { sf::err() << "Failed to check if window is viewable while requesting focus" << std::endl; @@ -637,9 +707,16 @@ void WindowImplX11::requestFocus() else { // Get current WM hints. - xcb_get_property_cookie_t hintsCookie = xcb_icccm_get_wm_hints_unchecked(m_connection, m_window); xcb_icccm_wm_hints_t hints; - xcb_icccm_get_wm_hints_reply(m_connection, hintsCookie, &hints, NULL); + xcb_icccm_get_wm_hints_reply( + m_connection, + xcb_icccm_get_wm_hints_unchecked( + m_connection, + m_window + ), + &hints, + NULL + ); // Even if no hints were returned, we can simply set the proper flags we need and go on. This is // different from Xlib where XAllocWMHints() has to be called. @@ -652,13 +729,18 @@ void WindowImplX11::requestFocus() //////////////////////////////////////////////////////////// bool WindowImplX11::hasFocus() const { - xcb_get_input_focus_cookie_t cookie = xcb_get_input_focus_unchecked(m_connection); - xcb_get_input_focus_reply_t* reply = xcb_get_input_focus_reply(m_connection, cookie, NULL); + xcb_get_input_focus_reply_t* reply = xcb_get_input_focus_reply( + m_connection, + xcb_get_input_focus_unchecked( + m_connection + ), + NULL + ); - bool focussed = (reply->focus == m_window); + bool focused = (reply->focus == m_window); free(reply); - return focussed; + return focused; } @@ -666,17 +748,31 @@ bool WindowImplX11::hasFocus() const void WindowImplX11::switchToFullscreen(const VideoMode& mode) { // Check if the XRandR extension is present - xcb_query_extension_reply_t* randr_ext = - xcb_query_extension_reply(m_connection, xcb_query_extension(m_connection, 5, "RANDR"), NULL); + static const std::string RANDR = "RANDR"; + xcb_query_extension_reply_t* randr_ext = xcb_query_extension_reply( + m_connection, + xcb_query_extension( + m_connection, + RANDR.size(), + RANDR.c_str() + ), + NULL + ); + if (randr_ext->present) { // Get the current configuration - 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, m_screen->root), - &errors); - if (! errors) + xcb_generic_error_t* error; + xcb_randr_get_screen_info_reply_t* config = xcb_randr_get_screen_info_reply( + m_connection, + xcb_randr_get_screen_info( + m_connection, + m_screen->root + ), + &error + ); + + if (!error) { // Save the current video mode before we switch to fullscreen m_oldVideoMode = config->sizeID; @@ -688,14 +784,19 @@ void WindowImplX11::switchToFullscreen(const VideoMode& mode) // Search a matching size for (int i = 0; i < config->nSizes; ++i) { - if ((sizes[i].width == static_cast(mode.width)) && (sizes[i].height == static_cast(mode.height))) + if ((sizes[i].width == static_cast(mode.width)) && + (sizes[i].height == static_cast(mode.height))) { // Switch to fullscreen mode - xcb_randr_set_screen_config(m_connection, - m_screen->root, - config->timestamp, - config->config_timestamp, - i, config->rotation, config->rate); + xcb_randr_set_screen_config( + m_connection, + m_screen->root, + config->timestamp, + config->config_timestamp, + i, + config->rotation, + config->rate + ); // Set "this" as the current fullscreen window fullscreenWindow = this; @@ -709,14 +810,17 @@ void WindowImplX11::switchToFullscreen(const VideoMode& mode) // 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 the configuration instance + free(error); free(config); } else { - // XRandr extension is not supported: we cannot use fullscreen mode + // XRandR extension is not supported: we cannot use fullscreen mode err() << "Fullscreen is not supported, switching to window mode" << std::endl; } + free(randr_ext); } @@ -726,30 +830,26 @@ void WindowImplX11::initialize() { // Get the atoms for registering the close event static const std::string WM_DELETE_WINDOW_NAME = "WM_DELETE_WINDOW"; - - xcb_intern_atom_cookie_t deleteWindowAtomRequest = xcb_intern_atom( - m_connection, - 0, - WM_DELETE_WINDOW_NAME.size(), - WM_DELETE_WINDOW_NAME.c_str() - ); xcb_intern_atom_reply_t* deleteWindowAtomReply = xcb_intern_atom_reply( m_connection, - deleteWindowAtomRequest, + xcb_intern_atom( + m_connection, + 0, + WM_DELETE_WINDOW_NAME.size(), + WM_DELETE_WINDOW_NAME.c_str() + ), NULL ); static const std::string WM_PROTOCOLS_NAME = "WM_PROTOCOLS"; - - xcb_intern_atom_cookie_t protocolsAtomRequest = xcb_intern_atom( - m_connection, - 0, - WM_PROTOCOLS_NAME.size(), - WM_PROTOCOLS_NAME.c_str() - ); xcb_intern_atom_reply_t* protocolsAtomReply = xcb_intern_atom_reply( m_connection, - protocolsAtomRequest, + xcb_intern_atom( + m_connection, + 0, + WM_PROTOCOLS_NAME.size(), + WM_PROTOCOLS_NAME.c_str() + ), NULL ); @@ -776,18 +876,25 @@ void WindowImplX11::initialize() // Create the input context m_inputMethod = XOpenIM(m_display, NULL, NULL, NULL); + if (m_inputMethod) { - m_inputContext = XCreateIC(m_inputMethod, - XNClientWindow, m_window, - XNFocusWindow, m_window, - XNInputStyle, XIMPreeditNothing | XIMStatusNothing, - (void*)NULL); + m_inputContext = XCreateIC( + m_inputMethod, + XNClientWindow, + m_window, + XNFocusWindow, + m_window, + XNInputStyle, + XIMPreeditNothing | XIMStatusNothing, + reinterpret_cast(NULL) + ); } else { m_inputContext = NULL; } + if (!m_inputContext) err() << "Failed to create input context for window -- TextEntered event won't be able to return unicode" << std::endl; @@ -815,10 +922,16 @@ void WindowImplX11::createHiddenCursor() 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 - xcb_create_cursor(m_connection, m_hiddenCursor, cursorPixmap, cursorPixmap, - 0, 0, 0, // Fore color - 0, 0, 0, // Back color - 0, 0); + xcb_create_cursor( + m_connection, + m_hiddenCursor, + cursorPixmap, + cursorPixmap, + 0, 0, 0, // Foreground RGB color + 0, 0, 0, // Background RGB color + 0, // X + 0 // Y + ); // We don't need the pixmap any longer, free it xcb_free_pixmap(m_connection, cursorPixmap); @@ -832,23 +945,33 @@ void WindowImplX11::cleanup() if (fullscreenWindow == this) { // Get current screen info - xcb_generic_error_t* errors; + xcb_generic_error_t* error; xcb_randr_get_screen_info_reply_t* config = xcb_randr_get_screen_info_reply( - m_connection, xcb_randr_get_screen_info(m_connection, m_screen->root), &errors); - if (!errors) + m_connection, + xcb_randr_get_screen_info( + m_connection, + m_screen->root + ), + &error + ); + + if (!error) { // Reset the video mode - xcb_randr_set_screen_config(m_connection, - m_screen->root, - CurrentTime, - config->config_timestamp, - m_oldVideoMode, - config->rotation, config->rate); - - // Free the configuration instance - free(config); + xcb_randr_set_screen_config( + m_connection, + m_screen->root, + CurrentTime, + config->config_timestamp, + m_oldVideoMode, + config->rotation, + config->rate + ); } - free(errors); + + // Free the configuration instance + free(error); + free(config); // Reset the fullscreen window fullscreenWindow = NULL; @@ -885,9 +1008,16 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) pushEvent(event); // If the window has been previously marked urgent (notification) as a result of a focus request, undo that - xcb_get_property_cookie_t hintsCookie = xcb_icccm_get_wm_hints_unchecked(m_connection, m_window); xcb_icccm_wm_hints_t hints; - xcb_icccm_get_wm_hints_reply(m_connection, hintsCookie, &hints, NULL); + xcb_icccm_get_wm_hints_reply( + m_connection, + xcb_icccm_get_wm_hints_unchecked( + m_connection, + m_window + ), + &hints, + NULL + ); // Remove urgency (notification) flag from hints hints.flags &= ~XUrgencyHint; @@ -949,8 +1079,8 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) 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.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); @@ -974,7 +1104,16 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) { Status status; Uint8 keyBuffer[16]; - int length = Xutf8LookupString(m_inputContext, &fake_event.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; @@ -1019,7 +1158,7 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) // has to be converted to an XEvent XKeyEvent fake_event; fake_event.display = m_display; - fake_event.state = e->state; + fake_event.state = e->state; fake_event.keycode = e->detail; XLookupString(&fake_event, buffer, 32, &symbol, NULL); @@ -1043,8 +1182,11 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* 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)) + 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; @@ -1069,8 +1211,11 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent) 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)) + 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;