Modernize memory management of X11 types
This commit is contained in:
parent
b391be2316
commit
27542637aa
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
61
src/SFML/Window/Unix/Utils.hpp
Normal file
61
src/SFML/Window/Unix/Utils.hpp
Normal 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
|
@ -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, ¤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<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, ¤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<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
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user