From 27542637aae77a0649904dd94f8aeb369b22e0ca Mon Sep 17 00:00:00 2001 From: Chris Thrasher Date: Sat, 29 Apr 2023 19:50:01 -0600 Subject: [PATCH] Modernize memory management of X11 types --- src/SFML/Window/CMakeLists.txt | 1 + src/SFML/Window/EglContext.cpp | 13 +- src/SFML/Window/Unix/CursorImpl.cpp | 21 ++- src/SFML/Window/Unix/GlxContext.cpp | 71 +++------ src/SFML/Window/Unix/Utils.hpp | 61 ++++++++ src/SFML/Window/Unix/VideoModeImpl.cpp | 39 ++--- src/SFML/Window/Unix/WindowImplX11.cpp | 206 +++++++++++++------------ 7 files changed, 232 insertions(+), 180 deletions(-) create mode 100644 src/SFML/Window/Unix/Utils.hpp diff --git a/src/SFML/Window/CMakeLists.txt b/src/SFML/Window/CMakeLists.txt index 5c2dd2a0..d355d4a2 100644 --- a/src/SFML/Window/CMakeLists.txt +++ b/src/SFML/Window/CMakeLists.txt @@ -123,6 +123,7 @@ elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_OPENBSD OR SFML_OS_NETBSD) ${SRCROOT}/Unix/SensorImpl.hpp ${SRCROOT}/Unix/Display.cpp ${SRCROOT}/Unix/Display.hpp + ${SRCROOT}/Unix/Utils.hpp ${SRCROOT}/Unix/VideoModeImpl.cpp ${SRCROOT}/Unix/VulkanImplX11.cpp ${SRCROOT}/Unix/VulkanImplX11.hpp diff --git a/src/SFML/Window/EglContext.cpp b/src/SFML/Window/EglContext.cpp index 2f07f6a5..5173abed 100644 --- a/src/SFML/Window/EglContext.cpp +++ b/src/SFML/Window/EglContext.cpp @@ -39,6 +39,8 @@ #include #endif #if defined(SFML_SYSTEM_LINUX) && !defined(SFML_USE_DRM) +#include + #include #endif @@ -424,10 +426,8 @@ XVisualInfo EglContext::selectBestVisual(::Display* XDisplay, unsigned int bitsP vTemplate.visualid = static_cast(nativeVisualId); // Get X11 visuals compatible with this EGL config - XVisualInfo *availableVisuals, bestVisual; - int visualCount = 0; - - availableVisuals = XGetVisualInfo(XDisplay, VisualIDMask, &vTemplate, &visualCount); + int visualCount = 0; + auto availableVisuals = X11Ptr XGetVisualInfo(XDisplay, VisualIDMask, &vTemplate, &visualCount)); if (visualCount == 0) { @@ -438,10 +438,7 @@ XVisualInfo EglContext::selectBestVisual(::Display* XDisplay, unsigned int bitsP } // Pick up the best one - bestVisual = availableVisuals[0]; - XFree(availableVisuals); - - return bestVisual; + return availableVisuals[0]; } #endif diff --git a/src/SFML/Window/Unix/CursorImpl.cpp b/src/SFML/Window/Unix/CursorImpl.cpp index b5aaf2c7..6bdf0d4e 100644 --- a/src/SFML/Window/Unix/CursorImpl.cpp +++ b/src/SFML/Window/Unix/CursorImpl.cpp @@ -27,6 +27,7 @@ //////////////////////////////////////////////////////////// #include #include +#include #include #include @@ -39,6 +40,15 @@ namespace sf::priv { +template <> +struct XDeleter +{ + void operator()(XcursorImage* cursorImage) const + { + XcursorImageDestroy(cursorImage); + } +}; + //////////////////////////////////////////////////////////// CursorImpl::CursorImpl() : m_display(openDisplay()) @@ -71,9 +81,9 @@ bool CursorImpl::loadFromPixels(const std::uint8_t* pixels, Vector2u size, Vecto bool CursorImpl::loadFromPixelsARGB(const std::uint8_t* pixels, Vector2u size, Vector2u hotspot) { // Create cursor image, convert from RGBA to ARGB. - XcursorImage* cursorImage = XcursorImageCreate(static_cast(size.x), static_cast(size.y)); - cursorImage->xhot = hotspot.x; - cursorImage->yhot = hotspot.y; + auto cursorImage = X11Ptr(XcursorImageCreate(static_cast(size.x), static_cast(size.y))); + cursorImage->xhot = hotspot.x; + cursorImage->yhot = hotspot.y; const std::size_t numPixels = static_cast(size.x) * static_cast(size.y); for (std::size_t pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) @@ -84,10 +94,7 @@ bool CursorImpl::loadFromPixelsARGB(const std::uint8_t* pixels, Vector2u size, V } // Create the cursor. - m_cursor = XcursorImageLoadCursor(m_display, cursorImage); - - // Free the resources - XcursorImageDestroy(cursorImage); + m_cursor = XcursorImageLoadCursor(m_display, cursorImage.get()); // We assume everything went fine... return true; diff --git a/src/SFML/Window/Unix/GlxContext.cpp b/src/SFML/Window/Unix/GlxContext.cpp index 43127792..534a1580 100644 --- a/src/SFML/Window/Unix/GlxContext.cpp +++ b/src/SFML/Window/Unix/GlxContext.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -314,14 +315,14 @@ XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPe const int screen = DefaultScreen(display); // Retrieve all the visuals - int count; - XVisualInfo* visuals = XGetVisualInfo(display, 0, nullptr, &count); + int count; + auto visuals = X11Ptr(XGetVisualInfo(display, 0, nullptr, &count)); if (visuals) { // Evaluate all the returned visuals, and pick the best one int bestScore = 0x7FFFFFFF; XVisualInfo bestVisual = XVisualInfo(); - for (int i = 0; i < count; ++i) + for (std::size_t i = 0; i < static_cast(count); ++i) { // Filter by screen if (visuals[i].screen != screen) @@ -392,9 +393,6 @@ XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPe } } - // Free the array of visuals - XFree(visuals); - return bestVisual; } else @@ -459,17 +457,15 @@ void GlxContext::updateSettingsFromWindow() // Get its visuals XVisualInfo tpl; - tpl.screen = DefaultScreen(m_display); - tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); - int nbVisuals = 0; - XVisualInfo* visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals); + tpl.screen = DefaultScreen(m_display); + tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); + int nbVisuals = 0; + auto visualInfo = X11Ptr(XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals)); if (!visualInfo) return; - updateSettingsFromVisualInfo(visualInfo); - - XFree(visualInfo); + updateSettingsFromVisualInfo(visualInfo.get()); } @@ -499,12 +495,13 @@ void GlxContext::createSurface(GlxContext* shared, const Vector2u& size, unsigne // We don't supply attributes to match against, since // the visual we are matching against was already // deemed suitable in selectBestVisual() - int nbConfigs = 0; - GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), nullptr, &nbConfigs); + int nbConfigs = 0; + auto configs = X11Ptr( + glXChooseFBConfig(m_display, DefaultScreen(m_display), nullptr, &nbConfigs)); - for (int i = 0; configs && (i < nbConfigs); ++i) + for (std::size_t i = 0; configs && (i < static_cast(nbConfigs)); ++i) { - XVisualInfo* visual = glXGetVisualFromFBConfig(m_display, configs[i]); + auto visual = X11Ptr(glXGetVisualFromFBConfig(m_display, configs[i])); if (!visual) continue; @@ -512,11 +509,8 @@ void GlxContext::createSurface(GlxContext* shared, const Vector2u& size, unsigne if (visual->visualid == visualInfo.visualid) { config = &configs[i]; - XFree(visual); break; } - - XFree(visual); } if (config) @@ -528,13 +522,8 @@ void GlxContext::createSurface(GlxContext* shared, const Vector2u& size, unsigne updateSettingsFromVisualInfo(&visualInfo); - XFree(configs); - return; } - - if (configs) - XFree(configs); } } @@ -583,7 +572,7 @@ void GlxContext::createContext(GlxContext* shared) // Get a working copy of the context settings const ContextSettings settings = m_settings; - XVisualInfo* visualInfo = nullptr; + X11Ptr visualInfo; if (m_pbuffer) { @@ -593,14 +582,11 @@ void GlxContext::createContext(GlxContext* shared) int attributes[] = {GLX_FBCONFIG_ID, static_cast(fbConfigId), 0, 0}; - int count = 0; - GLXFBConfig* fbconfig = glXChooseFBConfig(m_display, DefaultScreen(m_display), attributes, &count); + int count = 0; + auto fbconfig = X11Ptr(glXChooseFBConfig(m_display, DefaultScreen(m_display), attributes, &count)); if (count == 1) - visualInfo = glXGetVisualFromFBConfig(m_display, *fbconfig); - - if (fbconfig) - XFree(fbconfig); + visualInfo = X11Ptr(glXGetVisualFromFBConfig(m_display, *fbconfig)); } else { @@ -617,7 +603,7 @@ void GlxContext::createContext(GlxContext* shared) tpl.screen = DefaultScreen(m_display); tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); int nbVisuals = 0; - visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals); + visualInfo = X11Ptr(XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals)); } if (!visualInfo) @@ -648,12 +634,12 @@ void GlxContext::createContext(GlxContext* shared) // We don't supply attributes to match against, since // the visual we are matching against was already // deemed suitable in selectBestVisual() - int nbConfigs = 0; - GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), nullptr, &nbConfigs); + int nbConfigs = 0; + auto configs = X11Ptr(glXChooseFBConfig(m_display, DefaultScreen(m_display), nullptr, &nbConfigs)); - for (int i = 0; configs && (i < nbConfigs); ++i) + for (std::size_t i = 0; configs && (i < static_cast(nbConfigs)); ++i) { - XVisualInfo* visual = glXGetVisualFromFBConfig(m_display, configs[i]); + auto visual = X11Ptr(glXGetVisualFromFBConfig(m_display, configs[i])); if (!visual) continue; @@ -661,11 +647,8 @@ void GlxContext::createContext(GlxContext* shared) if (visual->visualid == visualInfo->visualid) { config = &configs[i]; - XFree(visual); break; } - - XFree(visual); } if (!config) @@ -753,9 +736,6 @@ void GlxContext::createContext(GlxContext* shared) } } } - - if (configs) - XFree(configs); } // If glXCreateContextAttribsARB failed, use glXCreateContext @@ -780,7 +760,7 @@ void GlxContext::createContext(GlxContext* shared) } // Create the context, using the target window's visual - m_context = glXCreateContext(m_display, visualInfo, toShare, true); + m_context = glXCreateContext(m_display, visualInfo.get(), toShare, true); #if defined(GLX_DEBUGGING) if (glxErrorOccurred) @@ -790,9 +770,6 @@ void GlxContext::createContext(GlxContext* shared) if (!m_context) err() << "Failed to create an OpenGL context for this window" << std::endl; - - // Free the visual info - XFree(visualInfo); } } // namespace sf::priv diff --git a/src/SFML/Window/Unix/Utils.hpp b/src/SFML/Window/Unix/Utils.hpp new file mode 100644 index 00000000..5b3c2e52 --- /dev/null +++ b/src/SFML/Window/Unix/Utils.hpp @@ -0,0 +1,61 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2023 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. +// +// 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. +// +//////////////////////////////////////////////////////////// + +#pragma once + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + +#include +#include + + +namespace sf::priv +{ +//////////////////////////////////////////////////////////// +/// \brief Class template for freeing X11 pointers +/// +/// Specialized elsewhere for types that are freed through +/// other means than XFree(). XFree() is the most common use +/// case though so it is the default. +/// +//////////////////////////////////////////////////////////// +template +struct XDeleter +{ + void operator()(T* data) const + { + XFree(data); + } +}; + +//////////////////////////////////////////////////////////// +/// \brief Class template for wrapping owning raw pointers from X11 +/// +//////////////////////////////////////////////////////////// +template +using X11Ptr = std::unique_ptr>>; +} // namespace sf::priv diff --git a/src/SFML/Window/Unix/VideoModeImpl.cpp b/src/SFML/Window/Unix/VideoModeImpl.cpp index cc50a93c..714fcfd4 100644 --- a/src/SFML/Window/Unix/VideoModeImpl.cpp +++ b/src/SFML/Window/Unix/VideoModeImpl.cpp @@ -26,6 +26,7 @@ // Headers //////////////////////////////////////////////////////////// #include +#include #include #include @@ -39,6 +40,17 @@ namespace sf::priv { +//////////////////////////////////////////////////////////// +template <> +struct XDeleter +{ + void operator()(XRRScreenConfiguration* config) const + { + XRRFreeScreenConfigInfo(config); + } +}; + + //////////////////////////////////////////////////////////// std::vector VideoModeImpl::getFullscreenModes() { @@ -56,21 +68,21 @@ std::vector VideoModeImpl::getFullscreenModes() if (XQueryExtension(display, "RANDR", &version, &version, &version)) { // Get the current configuration - XRRScreenConfiguration* config = XRRGetScreenInfo(display, RootWindow(display, screen)); + auto config = X11Ptr(XRRGetScreenInfo(display, RootWindow(display, screen))); if (config) { // Get the available screen sizes int nbSizes; - XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes); + XRRScreenSize* sizes = XRRConfigSizes(config.get(), &nbSizes); if (sizes && (nbSizes > 0)) { // Get the list of supported depths int nbDepths = 0; - int* depths = XListDepths(display, screen, &nbDepths); + auto depths = X11Ptr(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 (std::size_t i = 0; i < static_cast(nbDepths); ++i) { for (int j = 0; j < nbSizes; ++j) { @@ -80,7 +92,7 @@ std::vector VideoModeImpl::getFullscreenModes() static_cast(depths[i])); Rotation currentRotation; - XRRConfigRotations(config, ¤tRotation); + XRRConfigRotations(config.get(), ¤tRotation); if (currentRotation == RR_Rotate_90 || currentRotation == RR_Rotate_270) std::swap(mode.size.x, mode.size.y); @@ -90,14 +102,8 @@ std::vector VideoModeImpl::getFullscreenModes() modes.push_back(mode); } } - - // Free the array of depths - XFree(depths); } } - - // Free the configuration instance - XRRFreeScreenConfigInfo(config); } else { @@ -142,16 +148,16 @@ VideoMode VideoModeImpl::getDesktopMode() if (XQueryExtension(display, "RANDR", &version, &version, &version)) { // Get the current configuration - XRRScreenConfiguration* config = XRRGetScreenInfo(display, RootWindow(display, screen)); + auto config = X11Ptr(XRRGetScreenInfo(display, RootWindow(display, screen))); if (config) { // Get the current video mode Rotation currentRotation; - const int currentMode = XRRConfigCurrentConfiguration(config, ¤tRotation); + const int currentMode = XRRConfigCurrentConfiguration(config.get(), ¤tRotation); // Get the available screen sizes int nbSizes; - XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes); + XRRScreenSize* sizes = XRRConfigSizes(config.get(), &nbSizes); if (sizes && (nbSizes > 0)) { desktopMode = VideoMode({static_cast(sizes[currentMode].width), @@ -159,14 +165,11 @@ VideoMode VideoModeImpl::getDesktopMode() static_cast(DefaultDepth(display, screen))); Rotation modeRotation; - XRRConfigRotations(config, &modeRotation); + XRRConfigRotations(config.get(), &modeRotation); if (modeRotation == RR_Rotate_90 || modeRotation == RR_Rotate_270) std::swap(desktopMode.size.x, desktopMode.size.y); } - - // Free the configuration instance - XRRFreeScreenConfigInfo(config); } else { diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 393469b1..0955d05e 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -374,6 +375,50 @@ bool isWMAbsolutePositionGood() namespace sf::priv { +//////////////////////////////////////////////////////////// +template <> +struct XDeleter +{ + void operator()(XImage* image) const + { + XDestroyImage(image); + } +}; + + +//////////////////////////////////////////////////////////// +template <> +struct XDeleter +{ + void operator()(XRRScreenResources* res) const + { + XRRFreeScreenResources(res); + } +}; + + +//////////////////////////////////////////////////////////// +template <> +struct XDeleter +{ + void operator()(XRROutputInfo* outputInfo) const + { + XRRFreeOutputInfo(outputInfo); + } +}; + + +//////////////////////////////////////////////////////////// +template <> +struct XDeleter +{ + void operator()(XRRCrtcInfo* crtcInfo) const + { + XRRFreeCrtcInfo(crtcInfo); + } +}; + + //////////////////////////////////////////////////////////// WindowImplX11::WindowImplX11(WindowHandle handle) : m_isExternal(true) { @@ -486,11 +531,10 @@ m_cursorGrabbed(m_fullscreen) setProtocols(); // Set the WM initial state to the normal state - XWMHints* xHints = XAllocWMHints(); - xHints->flags = StateHint; - xHints->initial_state = NormalState; - XSetWMHints(m_display, m_window, xHints); - XFree(xHints); + XWMHints xHints{}; + xHints.flags = StateHint; + xHints.initial_state = NormalState; + XSetWMHints(m_display, m_window, &xHints); // If not in fullscreen, set the window's style (tell the window manager to // change our window's decorations and functions according to the requested style) @@ -565,19 +609,18 @@ m_cursorGrabbed(m_fullscreen) // 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 | USPosition; - sizeHints->min_width = sizeHints->max_width = static_cast(width); - sizeHints->min_height = sizeHints->max_height = static_cast(height); - sizeHints->x = windowPosition.x; - sizeHints->y = windowPosition.y; - XSetWMNormalHints(m_display, m_window, sizeHints); - XFree(sizeHints); + m_useSizeHints = true; + XSizeHints sizeHints{}; + sizeHints.flags = PMinSize | PMaxSize | USPosition; + sizeHints.min_width = sizeHints.max_width = static_cast(width); + sizeHints.min_height = sizeHints.max_height = static_cast(height); + sizeHints.x = windowPosition.x; + sizeHints.y = windowPosition.y; + XSetWMNormalHints(m_display, m_window, &sizeHints); } // Set the window's WM class (this can be used by window managers) - XClassHint* hint = XAllocClassHint(); + XClassHint hint{}; // The instance name should be something unique to this invocation // of the application but is rarely if ever used these days. @@ -585,7 +628,7 @@ m_cursorGrabbed(m_fullscreen) std::string executableName = findExecutableName().string(); std::vector windowInstance(executableName.size() + 1, 0); std::copy(executableName.begin(), executableName.end(), windowInstance.begin()); - hint->res_name = windowInstance.data(); + hint.res_name = windowInstance.data(); // The class name identifies a class of windows that // "are of the same type". We simply use the initial window name as @@ -593,11 +636,9 @@ m_cursorGrabbed(m_fullscreen) std::string ansiTitle = title.toAnsiString(); std::vector windowClass(ansiTitle.size() + 1, 0); std::copy(ansiTitle.begin(), ansiTitle.end(), windowClass.begin()); - hint->res_class = windowClass.data(); + hint.res_class = windowClass.data(); - XSetClassHint(m_display, m_window, hint); - - XFree(hint); + XSetClassHint(m_display, m_window, &hint); // Set the window's name setTitle(title); @@ -610,12 +651,11 @@ m_cursorGrabbed(m_fullscreen) { // Disable hint for min and max size, // otherwise some windows managers will not remove window decorations - XSizeHints* sizeHints = XAllocSizeHints(); - long flags = 0; - XGetWMNormalHints(m_display, m_window, sizeHints, &flags); - sizeHints->flags &= ~(PMinSize | PMaxSize); - XSetWMNormalHints(m_display, m_window, sizeHints); - XFree(sizeHints); + XSizeHints sizeHints{}; + long flags = 0; + XGetWMNormalHints(m_display, m_window, &sizeHints, &flags); + sizeHints.flags &= ~(PMinSize | PMaxSize); + XSetWMNormalHints(m_display, m_window, &sizeHints); setVideoMode(mode); switchToFullscreen(); @@ -841,12 +881,11 @@ void WindowImplX11::setSize(const Vector2u& size) // If resizing is disable for the window we have to update the size hints (required by some window managers). if (m_useSizeHints) { - XSizeHints* sizeHints = XAllocSizeHints(); - sizeHints->flags = PMinSize | PMaxSize; - sizeHints->min_width = sizeHints->max_width = static_cast(size.x); - sizeHints->min_height = sizeHints->max_height = static_cast(size.y); - XSetWMNormalHints(m_display, m_window, sizeHints); - XFree(sizeHints); + XSizeHints sizeHints{}; + sizeHints.flags = PMinSize | PMaxSize; + sizeHints.min_width = sizeHints.max_width = static_cast(size.x); + sizeHints.min_height = sizeHints.max_height = static_cast(size.y); + XSetWMNormalHints(m_display, m_window, &sizeHints); } XResizeWindow(m_display, m_window, size.x, size.y); @@ -925,7 +964,7 @@ void WindowImplX11::setTitle(const String& title) void WindowImplX11::setIcon(const Vector2u& size, const std::uint8_t* pixels) { // X11 wants BGRA pixels: swap red and blue channels - // Note: this memory will be freed by XDestroyImage + // Note: this memory will be freed by X11Ptr deleter auto* iconPixels = static_cast( std::malloc(static_cast(size.x) * static_cast(size.y) * 4)); for (std::size_t i = 0; i < static_cast(size.x) * static_cast(size.y); ++i) @@ -939,16 +978,8 @@ void WindowImplX11::setIcon(const Vector2u& size, const std::uint8_t* pixels) // Create the icon pixmap Visual* defVisual = DefaultVisual(m_display, m_screen); auto defDepth = static_cast(DefaultDepth(m_display, m_screen)); - XImage* iconImage = XCreateImage(m_display, - defVisual, - defDepth, - ZPixmap, - 0, - reinterpret_cast(iconPixels), - size.x, - size.y, - 32, - 0); + auto iconImage = X11Ptr( + XCreateImage(m_display, defVisual, defDepth, ZPixmap, 0, reinterpret_cast(iconPixels), size.x, size.y, 32, 0)); if (!iconImage) { err() << "Failed to set the window's icon" << std::endl; @@ -964,9 +995,8 @@ void WindowImplX11::setIcon(const Vector2u& size, const std::uint8_t* pixels) m_iconPixmap = XCreatePixmap(m_display, RootWindow(m_display, m_screen), size.x, size.y, defDepth); XGCValues values; GC iconGC = XCreateGC(m_display, m_iconPixmap, 0, &values); - XPutImage(m_display, m_iconPixmap, iconGC, iconImage, 0, 0, 0, 0, size.x, size.y); + XPutImage(m_display, m_iconPixmap, iconGC, iconImage.get(), 0, 0, 0, 0, size.x, size.y); XFreeGC(m_display, iconGC); - XDestroyImage(iconImage); // Create the mask pixmap (must have 1 bit depth) const std::size_t pitch = (size.x + 7) / 8; @@ -995,12 +1025,11 @@ void WindowImplX11::setIcon(const Vector2u& size, const std::uint8_t* pixels) 1); // Send our new icon to the window through the WMHints - XWMHints* hints = XAllocWMHints(); - hints->flags = IconPixmapHint | IconMaskHint; - hints->icon_pixmap = m_iconPixmap; - hints->icon_mask = m_iconMaskPixmap; - XSetWMHints(m_display, m_window, hints); - XFree(hints); + XWMHints hints{}; + hints.flags = IconPixmapHint | IconMaskHint; + hints.icon_pixmap = m_iconPixmap; + hints.icon_mask = m_iconMaskPixmap; + XSetWMHints(m_display, m_window, &hints); // ICCCM wants BGRA pixels: swap red and blue channels // ICCCM also wants the first 2 unsigned 32-bit values to be width and height @@ -1170,14 +1199,13 @@ void WindowImplX11::requestFocus() { // Otherwise: display urgency hint (flashing application logo) // Ensure WM hints exist, allocate if necessary - XWMHints* hints = XGetWMHints(m_display, m_window); + auto hints = X11Ptr(XGetWMHints(m_display, m_window)); if (hints == nullptr) - hints = XAllocWMHints(); + hints.reset(XAllocWMHints()); // Add urgency (notification) flag to hints hints->flags |= XUrgencyHint; - XSetWMHints(m_display, m_window, hints); - XFree(hints); + XSetWMHints(m_display, m_window, hints.get()); } } @@ -1265,35 +1293,27 @@ void WindowImplX11::setVideoMode(const VideoMode& mode) ::Window rootWindow = RootWindow(m_display, m_screen); // Get the screen resources - XRRScreenResources* res = XRRGetScreenResources(m_display, rootWindow); + auto res = X11Ptr(XRRGetScreenResources(m_display, rootWindow)); if (!res) { err() << "Failed to get the current screen resources for fullscreen mode, switching to window mode" << std::endl; return; } - RROutput output = getOutputPrimary(rootWindow, res, xRandRMajor, xRandRMinor); + RROutput output = getOutputPrimary(rootWindow, res.get(), xRandRMajor, xRandRMinor); // Get output info from output - XRROutputInfo* outputInfo = XRRGetOutputInfo(m_display, res, output); + auto outputInfo = X11Ptr(XRRGetOutputInfo(m_display, res.get(), output)); if (!outputInfo || outputInfo->connection == RR_Disconnected) { - XRRFreeScreenResources(res); - - // If outputInfo->connection == RR_Disconnected, free output info - if (outputInfo) - XRRFreeOutputInfo(outputInfo); - err() << "Failed to get output info for fullscreen mode, switching to window mode" << std::endl; return; } // Retrieve current RRMode, screen position and rotation - XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(m_display, res, outputInfo->crtc); + auto crtcInfo = X11Ptr(XRRGetCrtcInfo(m_display, res.get(), outputInfo->crtc)); if (!crtcInfo) { - XRRFreeScreenResources(res); - XRRFreeOutputInfo(outputInfo); err() << "Failed to get crtc info for fullscreen mode, switching to window mode" << std::endl; return; } @@ -1317,8 +1337,6 @@ void WindowImplX11::setVideoMode(const VideoMode& mode) if (!modeFound) { - XRRFreeScreenResources(res); - XRRFreeOutputInfo(outputInfo); err() << "Failed to find a matching RRMode for fullscreen mode, switching to window mode" << std::endl; return; } @@ -1328,14 +1346,19 @@ void WindowImplX11::setVideoMode(const VideoMode& mode) m_oldRRCrtc = outputInfo->crtc; // Switch to fullscreen mode - XRRSetCrtcConfig(m_display, res, outputInfo->crtc, CurrentTime, crtcInfo->x, crtcInfo->y, xRandMode, crtcInfo->rotation, &output, 1); + XRRSetCrtcConfig(m_display, + res.get(), + outputInfo->crtc, + CurrentTime, + crtcInfo->x, + crtcInfo->y, + xRandMode, + crtcInfo->rotation, + &output, + 1); // Set "this" as the current fullscreen window fullscreenWindow = this; - - XRRFreeScreenResources(res); - XRRFreeOutputInfo(outputInfo); - XRRFreeCrtcInfo(crtcInfo); } @@ -1352,7 +1375,7 @@ void WindowImplX11::resetVideoMode() int xRandRMinor; if (checkXRandR(xRandRMajor, xRandRMinor)) { - XRRScreenResources* res = XRRGetScreenResources(m_display, DefaultRootWindow(m_display)); + auto res = X11Ptr(XRRGetScreenResources(m_display, DefaultRootWindow(m_display))); if (!res) { err() << "Failed to get the current screen resources to reset the video mode" << std::endl; @@ -1360,10 +1383,9 @@ void WindowImplX11::resetVideoMode() } // Retrieve current screen position and rotation - XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(m_display, res, m_oldRRCrtc); + auto crtcInfo = X11Ptr(XRRGetCrtcInfo(m_display, res.get(), m_oldRRCrtc)); if (!crtcInfo) { - XRRFreeScreenResources(res); err() << "Failed to get crtc info to reset the video mode" << std::endl; return; } @@ -1385,7 +1407,7 @@ void WindowImplX11::resetVideoMode() } XRRSetCrtcConfig(m_display, - res, + res.get(), m_oldRRCrtc, CurrentTime, crtcInfo->x, @@ -1394,9 +1416,6 @@ void WindowImplX11::resetVideoMode() crtcInfo->rotation, &output, 1); - - XRRFreeCrtcInfo(crtcInfo); - XRRFreeScreenResources(res); } // Reset the fullscreen window @@ -1695,13 +1714,12 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) pushEvent(event); // If the window has been previously marked urgent (notification) as a result of a focus request, undo that - XWMHints* hints = XGetWMHints(m_display, m_window); + auto hints = X11Ptr(XGetWMHints(m_display, m_window)); if (hints != nullptr) { // Remove urgency (notification) flag from hints hints->flags &= ~XUrgencyHint; - XSetWMHints(m_display, m_window, hints); - XFree(hints); + XSetWMHints(m_display, m_window, hints.get()); } break; @@ -2117,7 +2135,7 @@ Vector2i WindowImplX11::getPrimaryMonitorPosition() ::Window rootWindow = RootWindow(m_display, m_screen); // Get the screen resources - XRRScreenResources* res = XRRGetScreenResources(m_display, rootWindow); + auto res = X11Ptr(XRRGetScreenResources(m_display, rootWindow)); if (!res) { err() << "Failed to get the current screen resources for primary monitor position" << std::endl; @@ -2130,28 +2148,20 @@ Vector2i WindowImplX11::getPrimaryMonitorPosition() if (!checkXRandR(xRandRMajor, xRandRMinor)) xRandRMajor = xRandRMinor = 0; - const RROutput output = getOutputPrimary(rootWindow, res, xRandRMajor, xRandRMinor); + const RROutput output = getOutputPrimary(rootWindow, res.get(), xRandRMajor, xRandRMinor); // Get output info from output - XRROutputInfo* outputInfo = XRRGetOutputInfo(m_display, res, output); + auto outputInfo = X11Ptr(XRRGetOutputInfo(m_display, res.get(), output)); if (!outputInfo || outputInfo->connection == RR_Disconnected) { - XRRFreeScreenResources(res); - - // If outputInfo->connection == RR_Disconnected, free output info - if (outputInfo) - XRRFreeOutputInfo(outputInfo); - err() << "Failed to get output info for primary monitor position" << std::endl; return monitorPosition; } // Retrieve current RRMode, screen position and rotation - XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(m_display, res, outputInfo->crtc); + auto crtcInfo = X11Ptr(XRRGetCrtcInfo(m_display, res.get(), outputInfo->crtc)); if (!crtcInfo) { - XRRFreeScreenResources(res); - XRRFreeOutputInfo(outputInfo); err() << "Failed to get crtc info for primary monitor position" << std::endl; return monitorPosition; } @@ -2159,10 +2169,6 @@ Vector2i WindowImplX11::getPrimaryMonitorPosition() monitorPosition.x = crtcInfo->x; monitorPosition.y = crtcInfo->y; - XRRFreeCrtcInfo(crtcInfo); - XRRFreeOutputInfo(outputInfo); - XRRFreeScreenResources(res); - return monitorPosition; }