summaryrefslogtreecommitdiff
path: root/src/SFML/Window/Unix/WindowImplX11.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/SFML/Window/Unix/WindowImplX11.cpp')
-rw-r--r--src/SFML/Window/Unix/WindowImplX11.cpp307
1 files changed, 257 insertions, 50 deletions
diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp
index e2c8d29..da69750 100644
--- a/src/SFML/Window/Unix/WindowImplX11.cpp
+++ b/src/SFML/Window/Unix/WindowImplX11.cpp
@@ -26,6 +26,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/Unix/WindowImplX11.hpp>
+#include <SFML/Window/Unix/ClipboardImpl.hpp>
#include <SFML/Window/Unix/Display.hpp>
#include <SFML/Window/Unix/InputImpl.hpp>
#include <SFML/System/Utf.hpp>
@@ -173,7 +174,7 @@ namespace
if (result != Success || actualType != XA_WINDOW || numItems != 1)
{
- if(result == Success)
+ if (result == Success)
XFree(data);
sf::priv::CloseDisplay(display);
@@ -205,7 +206,7 @@ namespace
if (result != Success || actualType != XA_WINDOW || numItems != 1)
{
- if(result == Success)
+ if (result == Success)
XFree(data);
sf::priv::CloseDisplay(display);
@@ -269,7 +270,7 @@ namespace
windowManagerName = sf::String::fromUtf8(begin, end);
}
- if(result == Success)
+ if (result == Success)
XFree(data);
sf::priv::CloseDisplay(display);
@@ -486,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),
@@ -534,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),
@@ -555,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;
@@ -571,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,
@@ -668,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);
}
@@ -707,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();
}
@@ -721,11 +743,11 @@ WindowImplX11::~WindowImplX11()
cleanup();
// Destroy icon pixmap
- if(m_iconPixmap)
+ if (m_iconPixmap)
XFreePixmap(m_display, m_iconPixmap);
// Destroy icon mask pixmap
- if(m_iconMaskPixmap)
+ if (m_iconMaskPixmap)
XFreePixmap(m_display, m_iconMaskPixmap);
// Destroy the cursor
@@ -779,6 +801,9 @@ void WindowImplX11::processEvents()
m_events.pop_front();
processEvent(event);
}
+
+ // Process clipboard window events
+ priv::ClipboardImpl::processEvents();
}
@@ -956,10 +981,10 @@ void WindowImplX11::setIcon(unsigned int width, unsigned int height, const Uint8
return;
}
- if(m_iconPixmap)
+ if (m_iconPixmap)
XFreePixmap(m_display, m_iconPixmap);
- if(m_iconMaskPixmap)
+ if (m_iconMaskPixmap)
XFreePixmap(m_display, m_iconMaskPixmap);
m_iconPixmap = XCreatePixmap(m_display, RootWindow(m_display, m_screen), width, height, defDepth);
@@ -1236,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;
}
- // Save the current video mode before we switch to fullscreen
- Rotation currentRotation;
- m_oldVideoMode = XRRConfigCurrentConfiguration(config, &currentRotation);
+ 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);
- // Get the available screen sizes
- int nbSizes;
- XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes);
+ // If outputInfo->connection == RR_Disconnected, free output info
+ if (outputInfo)
+ XRRFreeOutputInfo(outputInfo);
- // Search for a matching size
- for (int i = 0; (sizes && i < nbSizes); ++i)
+ 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)
{
- XRRConfigRotations(config, &currentRotation);
+ XRRFreeScreenResources(res);
+ XRRFreeOutputInfo(outputInfo);
+ err() << "Failed to get crtc info for fullscreen mode, switching to window mode" << std::endl;
+ return;
+ }
- if (currentRotation == RR_Rotate_90 || currentRotation == RR_Rotate_270)
- std::swap(sizes[i].height, sizes[i].width);
+ // Find RRMode to set
+ bool modeFound = false;
+ RRMode xRandMode;
- 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);
+ 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);
- // Set "this" as the current fullscreen window
- fullscreenWindow = this;
- break;
+ // 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;
}
}
- // Free the configuration instance
- XRRFreeScreenConfigInfo(config);
+ 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
+ m_oldVideoMode = crtcInfo->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);
+
+ // Set "this" as the current fullscreen window
+ fullscreenWindow = this;
+
+ XRRFreeScreenResources(res);
+ XRRFreeOutputInfo(outputInfo);
+ XRRFreeCrtcInfo(crtcInfo);
}
@@ -1291,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, &currentRotation);
+ 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;
+ }
+
+ // 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;
+ }
+
+ 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));
- // Reset the video mode
- XRRSetScreenConfig(m_display, config, RootWindow(m_display, m_screen), m_oldVideoMode, currentRotation, CurrentTime);
+ // Check if returned output is valid, otherwise use the first screen
+ if (output == None)
+ output = res->outputs[0];
+ }
+ else{
+ output = res->outputs[0];
+ }
- // Free the configuration instance
- XRRFreeScreenConfigInfo(config);
+ 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
@@ -1499,7 +1606,7 @@ void WindowImplX11::updateLastInputTime(::Time time)
{
Atom netWmUserTime = getAtom("_NET_WM_USER_TIME", true);
- if(netWmUserTime)
+ if (netWmUserTime)
{
XChangeProperty(m_display,
m_window,
@@ -1969,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