mirror of
https://github.com/SFML/SFML.git
synced 2024-12-01 15:51:04 +08:00
Use XRRSetCrtcConfig instead of XRRSetScreenConfig, in order to fix issue #1226. It should also fix issue #1224.
This commit is contained in:
parent
87aaa9e145
commit
46ce05cd9c
@ -487,6 +487,7 @@ m_inputMethod (NULL),
|
|||||||
m_inputContext (NULL),
|
m_inputContext (NULL),
|
||||||
m_isExternal (true),
|
m_isExternal (true),
|
||||||
m_oldVideoMode (0),
|
m_oldVideoMode (0),
|
||||||
|
m_oldRRCrtc (0),
|
||||||
m_hiddenCursor (0),
|
m_hiddenCursor (0),
|
||||||
m_lastCursor (None),
|
m_lastCursor (None),
|
||||||
m_keyRepeat (true),
|
m_keyRepeat (true),
|
||||||
@ -535,6 +536,7 @@ m_inputMethod (NULL),
|
|||||||
m_inputContext (NULL),
|
m_inputContext (NULL),
|
||||||
m_isExternal (false),
|
m_isExternal (false),
|
||||||
m_oldVideoMode (0),
|
m_oldVideoMode (0),
|
||||||
|
m_oldRRCrtc (0),
|
||||||
m_hiddenCursor (0),
|
m_hiddenCursor (0),
|
||||||
m_lastCursor (None),
|
m_lastCursor (None),
|
||||||
m_keyRepeat (true),
|
m_keyRepeat (true),
|
||||||
@ -556,8 +558,17 @@ m_lastInputTime (0)
|
|||||||
m_screen = DefaultScreen(m_display);
|
m_screen = DefaultScreen(m_display);
|
||||||
|
|
||||||
// Compute position and size
|
// Compute position and size
|
||||||
int left = m_fullscreen ? 0 : (DisplayWidth(m_display, m_screen) - mode.width) / 2;
|
Vector2i windowPosition;
|
||||||
int top = m_fullscreen ? 0 : (DisplayHeight(m_display, m_screen) - mode.height) / 2;
|
if(m_fullscreen)
|
||||||
|
{
|
||||||
|
windowPosition = getPrimaryMonitorPosition();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
windowPosition.x = (DisplayWidth(m_display, m_screen) - mode.width) / 2;
|
||||||
|
windowPosition.y = (DisplayWidth(m_display, m_screen) - mode.height) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
int width = mode.width;
|
int width = mode.width;
|
||||||
int height = mode.height;
|
int height = mode.height;
|
||||||
|
|
||||||
@ -572,7 +583,7 @@ m_lastInputTime (0)
|
|||||||
|
|
||||||
m_window = XCreateWindow(m_display,
|
m_window = XCreateWindow(m_display,
|
||||||
DefaultRootWindow(m_display),
|
DefaultRootWindow(m_display),
|
||||||
left, top,
|
windowPosition.x, windowPosition.y,
|
||||||
width, height,
|
width, height,
|
||||||
0,
|
0,
|
||||||
visualInfo.depth,
|
visualInfo.depth,
|
||||||
@ -669,9 +680,11 @@ m_lastInputTime (0)
|
|||||||
{
|
{
|
||||||
m_useSizeHints = true;
|
m_useSizeHints = true;
|
||||||
XSizeHints* sizeHints = XAllocSizeHints();
|
XSizeHints* sizeHints = XAllocSizeHints();
|
||||||
sizeHints->flags = PMinSize | PMaxSize;
|
sizeHints->flags = PMinSize | PMaxSize | USPosition;
|
||||||
sizeHints->min_width = sizeHints->max_width = width;
|
sizeHints->min_width = sizeHints->max_width = width;
|
||||||
sizeHints->min_height = sizeHints->max_height = height;
|
sizeHints->min_height = sizeHints->max_height = height;
|
||||||
|
sizeHints->x = windowPosition.x;
|
||||||
|
sizeHints->y = windowPosition.y;
|
||||||
XSetWMNormalHints(m_display, m_window, sizeHints);
|
XSetWMNormalHints(m_display, m_window, sizeHints);
|
||||||
XFree(sizeHints);
|
XFree(sizeHints);
|
||||||
}
|
}
|
||||||
@ -708,7 +721,15 @@ m_lastInputTime (0)
|
|||||||
// Set fullscreen video mode and switch to fullscreen if necessary
|
// Set fullscreen video mode and switch to fullscreen if necessary
|
||||||
if (m_fullscreen)
|
if (m_fullscreen)
|
||||||
{
|
{
|
||||||
setPosition(Vector2i(0, 0));
|
// 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);
|
||||||
|
|
||||||
setVideoMode(mode);
|
setVideoMode(mode);
|
||||||
switchToFullscreen();
|
switchToFullscreen();
|
||||||
}
|
}
|
||||||
@ -1240,53 +1261,99 @@ void WindowImplX11::setVideoMode(const VideoMode& mode)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Check if the XRandR extension is present
|
// Check if the XRandR extension is present
|
||||||
int version;
|
int xRandRMajor, xRandRMinor;
|
||||||
if (!XQueryExtension(m_display, "RANDR", &version, &version, &version))
|
if (!checkXRandR(xRandRMajor, xRandRMinor))
|
||||||
{
|
{
|
||||||
// XRandR extension is not supported: we cannot use fullscreen mode
|
// XRandR extension is not supported: we cannot use fullscreen mode
|
||||||
err() << "Fullscreen is not supported, switching to window mode" << std::endl;
|
err() << "Fullscreen is not supported, switching to window mode" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the current configuration
|
// Get root window
|
||||||
XRRScreenConfiguration* config = XRRGetScreenInfo(m_display, RootWindow(m_display, m_screen));
|
::Window rootWindow = RootWindow(m_display, m_screen);
|
||||||
|
|
||||||
if (!config)
|
// Get the screen resources
|
||||||
|
XRRScreenResources* res = XRRGetScreenResources(m_display, rootWindow);
|
||||||
|
if (!res)
|
||||||
{
|
{
|
||||||
// Failed to get the screen configuration
|
err() << "Failed to get the current screen resources for fullscreen mode, switching to window mode" << std::endl;
|
||||||
err() << "Failed to get the current screen configuration for fullscreen mode, switching to window mode" << std::endl;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RROutput output = getOutputPrimary(rootWindow, res, xRandRMajor, xRandRMinor);
|
||||||
|
|
||||||
|
// Get output info from output
|
||||||
|
XRROutputInfo* outputInfo = XRRGetOutputInfo(m_display, res, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retreive current RRMode, screen position and rotation
|
||||||
|
XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(m_display, res, outputInfo->crtc);
|
||||||
|
if (!crtcInfo)
|
||||||
|
{
|
||||||
|
XRRFreeScreenResources(res);
|
||||||
|
XRRFreeOutputInfo(outputInfo);
|
||||||
|
err() << "Failed to get crtc info for fullscreen mode, switching to window mode" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find RRMode to set
|
||||||
|
bool modeFound = false;
|
||||||
|
RRMode xRandMode;
|
||||||
|
|
||||||
|
for (int i = 0; (i < res->nmode) && !modeFound; i++)
|
||||||
|
{
|
||||||
|
if (crtcInfo->rotation == RR_Rotate_90 || crtcInfo->rotation == RR_Rotate_270)
|
||||||
|
std::swap(res->modes[i].height, res->modes[i].width);
|
||||||
|
|
||||||
|
// Check if screen size match
|
||||||
|
if (res->modes[i].width == static_cast<int>(mode.width) &&
|
||||||
|
res->modes[i].height == static_cast<int>(mode.height))
|
||||||
|
{
|
||||||
|
xRandMode = res->modes[i].id;
|
||||||
|
modeFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!modeFound)
|
||||||
|
{
|
||||||
|
XRRFreeScreenResources(res);
|
||||||
|
XRRFreeOutputInfo(outputInfo);
|
||||||
|
err() << "Failed to find a matching RRMode for fullscreen mode, switching to window mode" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the current video mode before we switch to fullscreen
|
// Save the current video mode before we switch to fullscreen
|
||||||
Rotation currentRotation;
|
m_oldVideoMode = crtcInfo->mode;
|
||||||
m_oldVideoMode = XRRConfigCurrentConfiguration(config, ¤tRotation);
|
m_oldRRCrtc = outputInfo->crtc;
|
||||||
|
|
||||||
// Get the available screen sizes
|
|
||||||
int nbSizes;
|
|
||||||
XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes);
|
|
||||||
|
|
||||||
// Search for a matching size
|
|
||||||
for (int i = 0; (sizes && i < nbSizes); ++i)
|
|
||||||
{
|
|
||||||
XRRConfigRotations(config, ¤tRotation);
|
|
||||||
|
|
||||||
if (currentRotation == RR_Rotate_90 || currentRotation == RR_Rotate_270)
|
|
||||||
std::swap(sizes[i].height, sizes[i].width);
|
|
||||||
|
|
||||||
if ((sizes[i].width == static_cast<int>(mode.width)) && (sizes[i].height == static_cast<int>(mode.height)))
|
|
||||||
{
|
|
||||||
// Switch to fullscreen mode
|
// Switch to fullscreen mode
|
||||||
XRRSetScreenConfig(m_display, config, RootWindow(m_display, m_screen), i, currentRotation, CurrentTime);
|
XRRSetCrtcConfig(m_display,
|
||||||
|
res,
|
||||||
|
outputInfo->crtc,
|
||||||
|
CurrentTime,
|
||||||
|
crtcInfo->x,
|
||||||
|
crtcInfo->y,
|
||||||
|
xRandMode,
|
||||||
|
crtcInfo->rotation,
|
||||||
|
&output,
|
||||||
|
1);
|
||||||
|
|
||||||
// Set "this" as the current fullscreen window
|
// Set "this" as the current fullscreen window
|
||||||
fullscreenWindow = this;
|
fullscreenWindow = this;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free the configuration instance
|
XRRFreeScreenResources(res);
|
||||||
XRRFreeScreenConfigInfo(config);
|
XRRFreeOutputInfo(outputInfo);
|
||||||
|
XRRFreeCrtcInfo(crtcInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1295,19 +1362,55 @@ void WindowImplX11::resetVideoMode()
|
|||||||
{
|
{
|
||||||
if (fullscreenWindow == this)
|
if (fullscreenWindow == this)
|
||||||
{
|
{
|
||||||
// Get current screen info
|
// Try to set old configuration
|
||||||
XRRScreenConfiguration* config = XRRGetScreenInfo(m_display, RootWindow(m_display, m_screen));
|
// Check if the XRandR extension
|
||||||
if (config)
|
int xRandRMajor, xRandRMinor;
|
||||||
|
if (checkXRandR(xRandRMajor, xRandRMinor))
|
||||||
{
|
{
|
||||||
// Get the current rotation
|
XRRScreenResources* res = XRRGetScreenResources(m_display, DefaultRootWindow(m_display));
|
||||||
Rotation currentRotation;
|
if (!res)
|
||||||
XRRConfigCurrentConfiguration(config, ¤tRotation);
|
{
|
||||||
|
err() << "Failed to get the current screen resources to reset the video mode" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Reset the video mode
|
// Retreive current screen position and rotation
|
||||||
XRRSetScreenConfig(m_display, config, RootWindow(m_display, m_screen), m_oldVideoMode, currentRotation, CurrentTime);
|
XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(m_display, res, m_oldRRCrtc);
|
||||||
|
if (!crtcInfo)
|
||||||
|
{
|
||||||
|
XRRFreeScreenResources(res);
|
||||||
|
err() << "Failed to get crtc info to reset the video mode" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Free the configuration instance
|
RROutput output;
|
||||||
XRRFreeScreenConfigInfo(config);
|
|
||||||
|
// if version >= 1.3 get the primary screen else take the first screen
|
||||||
|
if ((xRandRMajor == 1 && xRandRMinor >= 3) || xRandRMajor > 1)
|
||||||
|
{
|
||||||
|
output = XRRGetOutputPrimary(m_display, DefaultRootWindow(m_display));
|
||||||
|
|
||||||
|
// Check if returned output is valid, otherwise use the first screen
|
||||||
|
if (output == None)
|
||||||
|
output = res->outputs[0];
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
output = res->outputs[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
XRRSetCrtcConfig(m_display,
|
||||||
|
res,
|
||||||
|
m_oldRRCrtc,
|
||||||
|
CurrentTime,
|
||||||
|
crtcInfo->x,
|
||||||
|
crtcInfo->y,
|
||||||
|
m_oldVideoMode,
|
||||||
|
crtcInfo->rotation,
|
||||||
|
&output,
|
||||||
|
1);
|
||||||
|
|
||||||
|
XRRFreeCrtcInfo(crtcInfo);
|
||||||
|
XRRFreeScreenResources(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the fullscreen window
|
// Reset the fullscreen window
|
||||||
@ -1973,6 +2076,106 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool WindowImplX11::checkXRandR(int& xRandRMajor, int& xRandRMinor)
|
||||||
|
{
|
||||||
|
// Check if the XRandR extension is present
|
||||||
|
int version;
|
||||||
|
if (!XQueryExtension(m_display, "RANDR", &version, &version, &version))
|
||||||
|
{
|
||||||
|
err() << "XRandR extension is not supported" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check XRandR version, 1.2 required
|
||||||
|
if (!XRRQueryVersion(m_display, &xRandRMajor, &xRandRMinor) || xRandRMajor < 1 || (xRandRMajor == 1 && xRandRMinor < 2 ))
|
||||||
|
{
|
||||||
|
err() << "XRandR is too old" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
RROutput WindowImplX11::getOutputPrimary(::Window& rootWindow, XRRScreenResources* res, int xRandRMajor, int xRandRMinor)
|
||||||
|
{
|
||||||
|
// if xRandR version >= 1.3 get the primary screen else take the first screen
|
||||||
|
if ((xRandRMajor == 1 && xRandRMinor >= 3) || xRandRMajor > 1)
|
||||||
|
{
|
||||||
|
RROutput output = XRRGetOutputPrimary(m_display, rootWindow);
|
||||||
|
|
||||||
|
// Check if returned output is valid, otherwise use the first screen
|
||||||
|
if (output == None)
|
||||||
|
return res->outputs[0];
|
||||||
|
else
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
// xRandr version can't get the primary screen, use the first screen
|
||||||
|
return res->outputs[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Vector2i WindowImplX11::getPrimaryMonitorPosition()
|
||||||
|
{
|
||||||
|
Vector2i monitorPosition;
|
||||||
|
|
||||||
|
// Get root window
|
||||||
|
::Window rootWindow = RootWindow(m_display, m_screen);
|
||||||
|
|
||||||
|
// Get the screen resources
|
||||||
|
XRRScreenResources* res = XRRGetScreenResources(m_display, rootWindow);
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
err() << "Failed to get the current screen resources for.primary monitor position" << std::endl;
|
||||||
|
return monitorPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get xRandr version
|
||||||
|
int xRandRMajor, xRandRMinor;
|
||||||
|
if (!checkXRandR(xRandRMajor, xRandRMinor))
|
||||||
|
xRandRMajor = xRandRMinor = 0;
|
||||||
|
|
||||||
|
RROutput output = getOutputPrimary(rootWindow, res, xRandRMajor, xRandRMinor);
|
||||||
|
|
||||||
|
// Get output info from output
|
||||||
|
XRROutputInfo* outputInfo = XRRGetOutputInfo(m_display, res, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retreive current RRMode, screen position and rotation
|
||||||
|
XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(m_display, res, outputInfo->crtc);
|
||||||
|
if (!crtcInfo)
|
||||||
|
{
|
||||||
|
XRRFreeScreenResources(res);
|
||||||
|
XRRFreeOutputInfo(outputInfo);
|
||||||
|
err() << "Failed to get crtc info for.primary monitor position" << std::endl;
|
||||||
|
return monitorPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitorPosition.x = crtcInfo->x;
|
||||||
|
monitorPosition.y = crtcInfo->y;
|
||||||
|
|
||||||
|
XRRFreeCrtcInfo(crtcInfo);
|
||||||
|
XRRFreeOutputInfo(outputInfo);
|
||||||
|
XRRFreeScreenResources(res);
|
||||||
|
|
||||||
|
return monitorPosition;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include <SFML/Window/WindowStyle.hpp> // Prevent conflict with macro None from Xlib
|
#include <SFML/Window/WindowStyle.hpp> // Prevent conflict with macro None from Xlib
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <X11/extensions/Xrandr.h>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
@ -264,6 +265,38 @@ private:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool processEvent(XEvent& windowEvent);
|
bool processEvent(XEvent& windowEvent);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Check if a valid version of XRandR extension is present
|
||||||
|
///
|
||||||
|
/// \param xRandRMajor XRandR major version
|
||||||
|
/// \param xRandRMinor XRandR minor version
|
||||||
|
///
|
||||||
|
/// \return True if a valid XRandR version found, false otherwise
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool checkXRandR(int& xRandRMajor, int& xRandRMinor);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the RROutput of the primary monitor
|
||||||
|
///
|
||||||
|
/// \param rootWindow the root window
|
||||||
|
/// \param res screen resources
|
||||||
|
/// \param xRandRMajor XRandR major version
|
||||||
|
/// \param xRandRMinor XRandR minor version
|
||||||
|
///
|
||||||
|
/// \return RROutput of the primary monitor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
RROutput getOutputPrimary(::Window& rootWindow, XRRScreenResources* res, int xRandRMajor, int xRandRMinor);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get coordinates of the primary monitor
|
||||||
|
///
|
||||||
|
/// \return Position of the primary monitor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Vector2i getPrimaryMonitorPosition();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -275,6 +308,7 @@ private:
|
|||||||
std::deque<XEvent> m_events; ///< Queue we use to store pending events for this window
|
std::deque<XEvent> m_events; ///< Queue we use to store pending events for this window
|
||||||
bool m_isExternal; ///< Tell whether the window has been created externally or by SFML
|
bool m_isExternal; ///< Tell whether the window has been created externally or by SFML
|
||||||
int m_oldVideoMode; ///< Video mode in use before we switch to fullscreen
|
int m_oldVideoMode; ///< Video mode in use before we switch to fullscreen
|
||||||
|
RRCrtc m_oldRRCrtc; ///< RRCrtc in use before we switch to fullscreen
|
||||||
::Cursor m_hiddenCursor; ///< As X11 doesn't provide cursor hiding, we must create a transparent one
|
::Cursor m_hiddenCursor; ///< As X11 doesn't provide cursor hiding, we must create a transparent one
|
||||||
::Cursor m_lastCursor; ///< Last cursor used -- this data is not owned by the window and is required to be always valid
|
::Cursor m_lastCursor; ///< Last cursor used -- this data is not owned by the window and is required to be always valid
|
||||||
bool m_keyRepeat; ///< Is the KeyRepeat feature enabled?
|
bool m_keyRepeat; ///< Is the KeyRepeat feature enabled?
|
||||||
|
Loading…
Reference in New Issue
Block a user