Modernize memory management of X11 types

This commit is contained in:
Chris Thrasher 2023-04-29 19:50:01 -06:00
parent b391be2316
commit 27542637aa
7 changed files with 232 additions and 180 deletions

View File

@ -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

View File

@ -39,6 +39,8 @@
#include <SFML/System/Android/Activity.hpp>
#endif
#if defined(SFML_SYSTEM_LINUX) && !defined(SFML_USE_DRM)
#include <SFML/Window/Unix/Utils.hpp>
#include <X11/Xlib.h>
#endif
@ -424,10 +426,8 @@ XVisualInfo EglContext::selectBestVisual(::Display* XDisplay, unsigned int bitsP
vTemplate.visualid = static_cast<VisualID>(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<XVisualInfo[]> 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

View File

@ -27,6 +27,7 @@
////////////////////////////////////////////////////////////
#include <SFML/Window/Unix/CursorImpl.hpp>
#include <SFML/Window/Unix/Display.hpp>
#include <SFML/Window/Unix/Utils.hpp>
#include <X11/Xcursor/Xcursor.h>
#include <X11/Xutil.h>
@ -39,6 +40,15 @@
namespace sf::priv
{
template <>
struct XDeleter<XcursorImage>
{
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<int>(size.x), static_cast<int>(size.y));
cursorImage->xhot = hotspot.x;
cursorImage->yhot = hotspot.y;
auto cursorImage = X11Ptr<XcursorImage>(XcursorImageCreate(static_cast<int>(size.x), static_cast<int>(size.y)));
cursorImage->xhot = hotspot.x;
cursorImage->yhot = hotspot.y;
const std::size_t numPixels = static_cast<std::size_t>(size.x) * static_cast<std::size_t>(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;

View File

@ -28,6 +28,7 @@
#include <SFML/Window/Unix/Display.hpp>
#include <SFML/Window/Unix/GlxContext.hpp>
#include <SFML/Window/Unix/Utils.hpp>
#include <SFML/Window/Unix/WindowImplX11.hpp>
#include <SFML/System/Err.hpp>
@ -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<XVisualInfo[]>(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<std::size_t>(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<XVisualInfo>(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<GLXFBConfig[]>(
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<std::size_t>(nbConfigs)); ++i)
{
XVisualInfo* visual = glXGetVisualFromFBConfig(m_display, configs[i]);
auto visual = X11Ptr<XVisualInfo>(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<XVisualInfo> visualInfo;
if (m_pbuffer)
{
@ -593,14 +582,11 @@ void GlxContext::createContext(GlxContext* shared)
int attributes[] = {GLX_FBCONFIG_ID, static_cast<int>(fbConfigId), 0, 0};
int count = 0;
GLXFBConfig* fbconfig = glXChooseFBConfig(m_display, DefaultScreen(m_display), attributes, &count);
int count = 0;
auto fbconfig = X11Ptr<GLXFBConfig>(glXChooseFBConfig(m_display, DefaultScreen(m_display), attributes, &count));
if (count == 1)
visualInfo = glXGetVisualFromFBConfig(m_display, *fbconfig);
if (fbconfig)
XFree(fbconfig);
visualInfo = X11Ptr<XVisualInfo>(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<XVisualInfo>(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<GLXFBConfig[]>(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<std::size_t>(nbConfigs)); ++i)
{
XVisualInfo* visual = glXGetVisualFromFBConfig(m_display, configs[i]);
auto visual = X11Ptr<XVisualInfo>(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

View File

@ -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 <X11/Xlib.h>
#include <memory>
#include <type_traits>
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 <typename T>
struct XDeleter
{
void operator()(T* data) const
{
XFree(data);
}
};
////////////////////////////////////////////////////////////
/// \brief Class template for wrapping owning raw pointers from X11
///
////////////////////////////////////////////////////////////
template <typename T>
using X11Ptr = std::unique_ptr<T, XDeleter<std::remove_all_extents_t<T>>>;
} // namespace sf::priv

View File

@ -26,6 +26,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/Unix/Display.hpp>
#include <SFML/Window/Unix/Utils.hpp>
#include <SFML/Window/VideoModeImpl.hpp>
#include <SFML/System/Err.hpp>
@ -39,6 +40,17 @@
namespace sf::priv
{
////////////////////////////////////////////////////////////
template <>
struct XDeleter<XRRScreenConfiguration>
{
void operator()(XRRScreenConfiguration* config) const
{
XRRFreeScreenConfigInfo(config);
}
};
////////////////////////////////////////////////////////////
std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
{
@ -56,21 +68,21 @@ std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
if (XQueryExtension(display, "RANDR", &version, &version, &version))
{
// Get the current configuration
XRRScreenConfiguration* config = XRRGetScreenInfo(display, RootWindow(display, screen));
auto config = X11Ptr<XRRScreenConfiguration>(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<int[]>(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<std::size_t>(nbDepths); ++i)
{
for (int j = 0; j < nbSizes; ++j)
{
@ -80,7 +92,7 @@ std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
static_cast<unsigned int>(depths[i]));
Rotation currentRotation;
XRRConfigRotations(config, &currentRotation);
XRRConfigRotations(config.get(), &currentRotation);
if (currentRotation == RR_Rotate_90 || currentRotation == RR_Rotate_270)
std::swap(mode.size.x, mode.size.y);
@ -90,14 +102,8 @@ std::vector<VideoMode> 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<XRRScreenConfiguration>(XRRGetScreenInfo(display, RootWindow(display, screen)));
if (config)
{
// Get the current video mode
Rotation currentRotation;
const int currentMode = XRRConfigCurrentConfiguration(config, &currentRotation);
const int currentMode = XRRConfigCurrentConfiguration(config.get(), &currentRotation);
// 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<unsigned int>(sizes[currentMode].width),
@ -159,14 +165,11 @@ VideoMode VideoModeImpl::getDesktopMode()
static_cast<unsigned int>(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
{

View File

@ -30,6 +30,7 @@
#include <SFML/Window/Unix/Display.hpp>
#include <SFML/Window/Unix/InputImpl.hpp>
#include <SFML/Window/Unix/KeyboardImpl.hpp>
#include <SFML/Window/Unix/Utils.hpp>
#include <SFML/Window/Unix/WindowImplX11.hpp>
#include <SFML/System/Err.hpp>
@ -374,6 +375,50 @@ bool isWMAbsolutePositionGood()
namespace sf::priv
{
////////////////////////////////////////////////////////////
template <>
struct XDeleter<XImage>
{
void operator()(XImage* image) const
{
XDestroyImage(image);
}
};
////////////////////////////////////////////////////////////
template <>
struct XDeleter<XRRScreenResources>
{
void operator()(XRRScreenResources* res) const
{
XRRFreeScreenResources(res);
}
};
////////////////////////////////////////////////////////////
template <>
struct XDeleter<XRROutputInfo>
{
void operator()(XRROutputInfo* outputInfo) const
{
XRRFreeOutputInfo(outputInfo);
}
};
////////////////////////////////////////////////////////////
template <>
struct XDeleter<XRRCrtcInfo>
{
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<int>(width);
sizeHints->min_height = sizeHints->max_height = static_cast<int>(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<int>(width);
sizeHints.min_height = sizeHints.max_height = static_cast<int>(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<char> 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<char> 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<int>(size.x);
sizeHints->min_height = sizeHints->max_height = static_cast<int>(size.y);
XSetWMNormalHints(m_display, m_window, sizeHints);
XFree(sizeHints);
XSizeHints sizeHints{};
sizeHints.flags = PMinSize | PMaxSize;
sizeHints.min_width = sizeHints.max_width = static_cast<int>(size.x);
sizeHints.min_height = sizeHints.max_height = static_cast<int>(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<XImage> deleter
auto* iconPixels = static_cast<std::uint8_t*>(
std::malloc(static_cast<std::size_t>(size.x) * static_cast<std::size_t>(size.y) * 4));
for (std::size_t i = 0; i < static_cast<std::size_t>(size.x) * static_cast<std::size_t>(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<unsigned int>(DefaultDepth(m_display, m_screen));
XImage* iconImage = XCreateImage(m_display,
defVisual,
defDepth,
ZPixmap,
0,
reinterpret_cast<char*>(iconPixels),
size.x,
size.y,
32,
0);
auto iconImage = X11Ptr<XImage>(
XCreateImage(m_display, defVisual, defDepth, ZPixmap, 0, reinterpret_cast<char*>(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<XWMHints>(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<XRRScreenResources>(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<XRROutputInfo>(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<XRRCrtcInfo>(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<XRRScreenResources>(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<XRRCrtcInfo>(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<XWMHints>(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<XRRScreenResources>(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<XRROutputInfo>(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<XRRCrtcInfo>(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;
}