diff options
Diffstat (limited to 'src/SFML/Window/Unix/VideoModeImpl.cpp')
-rw-r--r-- | src/SFML/Window/Unix/VideoModeImpl.cpp | 262 |
1 files changed, 161 insertions, 101 deletions
diff --git a/src/SFML/Window/Unix/VideoModeImpl.cpp b/src/SFML/Window/Unix/VideoModeImpl.cpp index c7e6204..9ee812f 100644 --- a/src/SFML/Window/Unix/VideoModeImpl.cpp +++ b/src/SFML/Window/Unix/VideoModeImpl.cpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org) // // This software is provided 'as-is', without any express or implied warranty. // In no event will the authors be held liable for any damages arising from the use of this software. @@ -27,9 +27,9 @@ //////////////////////////////////////////////////////////// #include <SFML/Window/VideoModeImpl.hpp> #include <SFML/Window/Unix/Display.hpp> +#include <SFML/Window/Unix/ScopedXcbPtr.hpp> #include <SFML/System/Err.hpp> -#include <X11/Xlib.h> -#include <X11/extensions/Xrandr.h> +#include <xcb/randr.h> #include <algorithm> @@ -43,73 +43,96 @@ std::vector<VideoMode> VideoModeImpl::getFullscreenModes() std::vector<VideoMode> modes; // Open a connection with the X server - Display* display = OpenDisplay(); - if (display) + xcb_connection_t* connection = OpenConnection(); + + // Retrieve the default screen + xcb_screen_t* screen = XCBDefaultScreen(connection); + + ScopedXcbPtr<xcb_generic_error_t> error(NULL); + + const xcb_query_extension_reply_t* randrExt = xcb_get_extension_data(connection, &xcb_randr_id); + + if (!randrExt || !randrExt->present) { - // Retrieve the default screen number - int screen = DefaultScreen(display); + // Randr extension is not supported: we cannot get the video modes + err() << "Failed to use the RandR extension while trying to get the supported video modes" << std::endl; - // Check if the XRandR extension is present - int version; - if (XQueryExtension(display, "RANDR", &version, &version, &version)) - { - // Get the current configuration - XRRScreenConfiguration* config = XRRGetScreenInfo(display, RootWindow(display, screen)); - if (config) - { - // Get the available screen sizes - int nbSizes; - XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes); - if (sizes && (nbSizes > 0)) - { - // Get the list of supported depths - int nbDepths = 0; - int* depths = XListDepths(display, screen, &nbDepths); - if (depths && (nbDepths > 0)) - { - // Combine depths and sizes to fill the array of supported modes - for (int i = 0; i < nbDepths; ++i) - { - for (int j = 0; j < nbSizes; ++j) - { - // Convert to VideoMode - VideoMode mode(sizes[j].width, sizes[j].height, depths[i]); - - // 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; - } - } - 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; - } + // Close the connection with the X server + CloseConnection(connection); + + return modes; + } + + // Load RandR and check its version + ScopedXcbPtr<xcb_randr_query_version_reply_t> randrVersion(xcb_randr_query_version_reply( + connection, + xcb_randr_query_version( + connection, + 1, + 1 + ), + &error + )); + + if (error) + { + err() << "Failed to load the RandR extension while trying to get the supported video modes" << std::endl; // Close the connection with the X server - CloseDisplay(display); + CloseConnection(connection); + + return modes; } - else + + // Get the current configuration + ScopedXcbPtr<xcb_randr_get_screen_info_reply_t> config(xcb_randr_get_screen_info_reply( + connection, + xcb_randr_get_screen_info( + connection, + screen->root + ), + &error + )); + + if (error) + { + // Failed to get the screen configuration + err() << "Failed to retrieve the screen configuration while trying to get the supported video modes" << std::endl; + + // Close the connection with the X server + CloseConnection(connection); + + return modes; + } + + // Get the available screen sizes + xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config.get()); + if (sizes && (config->nSizes > 0)) { - // 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; + // 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) + { + // Convert to VideoMode + VideoMode mode(sizes[j].width, sizes[j].height, iter.data->depth); + + if (config->rotation == XCB_RANDR_ROTATION_ROTATE_90 || + config->rotation == XCB_RANDR_ROTATION_ROTATE_270) + std::swap(mode.width, mode.height); + + // 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); + } + } } + // Close the connection with the X server + CloseConnection(connection); + return modes; } @@ -120,54 +143,91 @@ VideoMode VideoModeImpl::getDesktopMode() VideoMode desktopMode; // Open a connection with the X server - Display* display = OpenDisplay(); - if (display) + xcb_connection_t* connection = OpenConnection(); + + // Retrieve the default screen + xcb_screen_t* screen = XCBDefaultScreen(connection); + + ScopedXcbPtr<xcb_generic_error_t> error(NULL); + + // Check if the RandR extension is present + const xcb_query_extension_reply_t* randrExt = xcb_get_extension_data(connection, &xcb_randr_id); + + if (!randrExt || !randrExt->present) { - // Retrieve the default screen number - int screen = DefaultScreen(display); + // Randr extension is not supported: we cannot get the video modes + err() << "Failed to use the RandR extension while trying to get the desktop video mode" << std::endl; - // Check if the XRandR extension is present - int version; - if (XQueryExtension(display, "RANDR", &version, &version, &version)) - { - // Get the current configuration - XRRScreenConfiguration* config = XRRGetScreenInfo(display, RootWindow(display, screen)); - if (config) - { - // Get the current video mode - Rotation currentRotation; - int currentMode = XRRConfigCurrentConfiguration(config, ¤tRotation); - - // Get the available screen sizes - int nbSizes; - XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes); - if (sizes && (nbSizes > 0)) - desktopMode = VideoMode(sizes[currentMode].width, sizes[currentMode].height, DefaultDepth(display, screen)); - - // 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 desktop video modes" << std::endl; - } - } - 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; - } + // Close the connection with the X server + CloseConnection(connection); + + return desktopMode; + } + + // Load RandR and check its version + ScopedXcbPtr<xcb_randr_query_version_reply_t> randrVersion(xcb_randr_query_version_reply( + connection, + xcb_randr_query_version( + connection, + 1, + 1 + ), + &error + )); + + if (error) + { + err() << "Failed to load the RandR extension while trying to get the desktop video mode" << std::endl; // Close the connection with the X server - CloseDisplay(display); + CloseConnection(connection); + + return desktopMode; + } + + // Get the current configuration + ScopedXcbPtr<xcb_randr_get_screen_info_reply_t> config(xcb_randr_get_screen_info_reply( + connection, + xcb_randr_get_screen_info( + connection, + screen->root + ), + &error + )); + + if (error) + { + // Failed to get the screen configuration + err() << "Failed to retrieve the screen configuration while trying to get the desktop video mode" << std::endl; + + // Close the connection with the X server + CloseConnection(connection); + + return desktopMode; + } + + // 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.get()); + xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config.get()); + if (sizes && (nbSizes > 0)) + { + desktopMode = VideoMode(sizes[currentMode].width, sizes[currentMode].height, screen->root_depth); + + if (config->rotation == XCB_RANDR_ROTATION_ROTATE_90 || + config->rotation == XCB_RANDR_ROTATION_ROTATE_270) + std::swap(desktopMode.width, desktopMode.height); } 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; + err() << "Failed to retrieve any screen sizes while trying to get the desktop video mode" << std::endl; } + // Close the connection with the X server + CloseConnection(connection); + return desktopMode; } |