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_isExternal (true),
|
||||
m_oldVideoMode (0),
|
||||
m_oldRRCrtc (0),
|
||||
m_hiddenCursor (0),
|
||||
m_lastCursor (None),
|
||||
m_keyRepeat (true),
|
||||
@ -535,6 +536,7 @@ m_inputMethod (NULL),
|
||||
m_inputContext (NULL),
|
||||
m_isExternal (false),
|
||||
m_oldVideoMode (0),
|
||||
m_oldRRCrtc (0),
|
||||
m_hiddenCursor (0),
|
||||
m_lastCursor (None),
|
||||
m_keyRepeat (true),
|
||||
@ -556,8 +558,17 @@ m_lastInputTime (0)
|
||||
m_screen = DefaultScreen(m_display);
|
||||
|
||||
// Compute position and size
|
||||
int left = m_fullscreen ? 0 : (DisplayWidth(m_display, m_screen) - mode.width) / 2;
|
||||
int top = m_fullscreen ? 0 : (DisplayHeight(m_display, m_screen) - mode.height) / 2;
|
||||
Vector2i windowPosition;
|
||||
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 height = mode.height;
|
||||
|
||||
@ -572,7 +583,7 @@ m_lastInputTime (0)
|
||||
|
||||
m_window = XCreateWindow(m_display,
|
||||
DefaultRootWindow(m_display),
|
||||
left, top,
|
||||
windowPosition.x, windowPosition.y,
|
||||
width, height,
|
||||
0,
|
||||
visualInfo.depth,
|
||||
@ -669,9 +680,11 @@ m_lastInputTime (0)
|
||||
{
|
||||
m_useSizeHints = true;
|
||||
XSizeHints* sizeHints = XAllocSizeHints();
|
||||
sizeHints->flags = PMinSize | PMaxSize;
|
||||
sizeHints->flags = PMinSize | PMaxSize | USPosition;
|
||||
sizeHints->min_width = sizeHints->max_width = width;
|
||||
sizeHints->min_height = sizeHints->max_height = height;
|
||||
sizeHints->x = windowPosition.x;
|
||||
sizeHints->y = windowPosition.y;
|
||||
XSetWMNormalHints(m_display, m_window, sizeHints);
|
||||
XFree(sizeHints);
|
||||
}
|
||||
@ -708,7 +721,15 @@ m_lastInputTime (0)
|
||||
// Set fullscreen video mode and switch to fullscreen if necessary
|
||||
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);
|
||||
switchToFullscreen();
|
||||
}
|
||||
@ -1240,53 +1261,99 @@ void WindowImplX11::setVideoMode(const VideoMode& mode)
|
||||
return;
|
||||
|
||||
// Check if the XRandR extension is present
|
||||
int version;
|
||||
if (!XQueryExtension(m_display, "RANDR", &version, &version, &version))
|
||||
int xRandRMajor, xRandRMinor;
|
||||
if (!checkXRandR(xRandRMajor, xRandRMinor))
|
||||
{
|
||||
// XRandR extension is not supported: we cannot use fullscreen mode
|
||||
err() << "Fullscreen is not supported, switching to window mode" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the current configuration
|
||||
XRRScreenConfiguration* config = XRRGetScreenInfo(m_display, RootWindow(m_display, m_screen));
|
||||
// Get root window
|
||||
::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 configuration for fullscreen mode, switching to window mode" << std::endl;
|
||||
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);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Save the current video mode before we switch to fullscreen
|
||||
Rotation currentRotation;
|
||||
m_oldVideoMode = XRRConfigCurrentConfiguration(config, ¤tRotation);
|
||||
m_oldVideoMode = crtcInfo->mode;
|
||||
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
|
||||
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
|
||||
fullscreenWindow = this;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Free the configuration instance
|
||||
XRRFreeScreenConfigInfo(config);
|
||||
XRRFreeScreenResources(res);
|
||||
XRRFreeOutputInfo(outputInfo);
|
||||
XRRFreeCrtcInfo(crtcInfo);
|
||||
}
|
||||
|
||||
|
||||
@ -1295,19 +1362,55 @@ void WindowImplX11::resetVideoMode()
|
||||
{
|
||||
if (fullscreenWindow == this)
|
||||
{
|
||||
// Get current screen info
|
||||
XRRScreenConfiguration* config = XRRGetScreenInfo(m_display, RootWindow(m_display, m_screen));
|
||||
if (config)
|
||||
// Try to set old configuration
|
||||
// Check if the XRandR extension
|
||||
int xRandRMajor, xRandRMinor;
|
||||
if (checkXRandR(xRandRMajor, xRandRMinor))
|
||||
{
|
||||
// Get the current rotation
|
||||
Rotation currentRotation;
|
||||
XRRConfigCurrentConfiguration(config, ¤tRotation);
|
||||
XRRScreenResources* res = XRRGetScreenResources(m_display, DefaultRootWindow(m_display));
|
||||
if (!res)
|
||||
{
|
||||
err() << "Failed to get the current screen resources to reset the video mode" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset the video mode
|
||||
XRRSetScreenConfig(m_display, config, RootWindow(m_display, m_screen), m_oldVideoMode, currentRotation, CurrentTime);
|
||||
// Retreive current screen position and rotation
|
||||
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
|
||||
XRRFreeScreenConfigInfo(config);
|
||||
RROutput output;
|
||||
|
||||
// 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
|
||||
@ -1973,6 +2076,106 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
|
||||
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 sf
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <SFML/Window/WindowStyle.hpp> // Prevent conflict with macro None from Xlib
|
||||
#include <X11/Xlib.h>
|
||||
#include <deque>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
@ -264,6 +265,38 @@ private:
|
||||
////////////////////////////////////////////////////////////
|
||||
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
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -275,6 +308,7 @@ private:
|
||||
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
|
||||
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_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?
|
||||
|
Loading…
Reference in New Issue
Block a user