1 ////////////////////////////////////////////////////////////
2 //
3 // SFML - Simple and Fast Multimedia Library
4 // Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
5 //
6 // This software is provided 'as-is', without any express or implied warranty.
7 // In no event will the authors be held liable for any damages arising from the use of this software.
8 //
9 // Permission is granted to anyone to use this software for any purpose,
10 // including commercial applications, and to alter it and redistribute it freely,
11 // subject to the following restrictions:
12 //
13 // 1. The origin of this software must not be misrepresented;
14 //    you must not claim that you wrote the original software.
15 //    If you use this software in a product, an acknowledgment
16 //    in the product documentation would be appreciated but is not required.
17 //
18 // 2. Altered source versions must be plainly marked as such,
19 //    and must not be misrepresented as being the original software.
20 //
21 // 3. This notice may not be removed or altered from any source distribution.
22 //
23 ////////////////////////////////////////////////////////////
24 
25 ////////////////////////////////////////////////////////////
26 // Headers
27 ////////////////////////////////////////////////////////////
28 #include <SFML/Window/VideoModeImpl.hpp>
29 #include <SFML/Window/Unix/Display.hpp>
30 #include <SFML/System/Err.hpp>
31 #include <X11/Xlib.h>
32 #include <X11/extensions/Xrandr.h>
33 #include <algorithm>
34 
35 
36 namespace sf
37 {
38 namespace priv
39 {
40 ////////////////////////////////////////////////////////////
getFullscreenModes()41 std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
42 {
43     std::vector<VideoMode> modes;
44 
45     // Open a connection with the X server
46     Display* display = OpenDisplay();
47     if (display)
48     {
49         // Retrieve the default screen number
50         int screen = DefaultScreen(display);
51 
52         // Check if the XRandR extension is present
53         int version;
54         if (XQueryExtension(display, "RANDR", &version, &version, &version))
55         {
56             // Get the current configuration
57             XRRScreenConfiguration* config = XRRGetScreenInfo(display, RootWindow(display, screen));
58             if (config)
59             {
60                 // Get the available screen sizes
61                 int nbSizes;
62                 XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes);
63                 if (sizes && (nbSizes > 0))
64                 {
65                     // Get the list of supported depths
66                     int nbDepths = 0;
67                     int* depths = XListDepths(display, screen, &nbDepths);
68                     if (depths && (nbDepths > 0))
69                     {
70                         // Combine depths and sizes to fill the array of supported modes
71                         for (int i = 0; i < nbDepths; ++i)
72                         {
73                             for (int j = 0; j < nbSizes; ++j)
74                             {
75                                 // Convert to VideoMode
76                                 VideoMode mode(sizes[j].width, sizes[j].height, depths[i]);
77 
78                                 Rotation currentRotation;
79                                 XRRConfigRotations(config, &currentRotation);
80 
81                                 if (currentRotation == RR_Rotate_90 || currentRotation == RR_Rotate_270)
82                                     std::swap(mode.width, mode.height);
83 
84                                 // Add it only if it is not already in the array
85                                 if (std::find(modes.begin(), modes.end(), mode) == modes.end())
86                                     modes.push_back(mode);
87                             }
88                         }
89 
90                         // Free the array of depths
91                         XFree(depths);
92                     }
93                 }
94 
95                 // Free the configuration instance
96                 XRRFreeScreenConfigInfo(config);
97             }
98             else
99             {
100                 // Failed to get the screen configuration
101                 err() << "Failed to retrieve the screen configuration while trying to get the supported video modes" << std::endl;
102             }
103         }
104         else
105         {
106             // XRandr extension is not supported: we cannot get the video modes
107             err() << "Failed to use the XRandR extension while trying to get the supported video modes" << std::endl;
108         }
109 
110         // Close the connection with the X server
111         CloseDisplay(display);
112     }
113     else
114     {
115         // We couldn't connect to the X server
116         err() << "Failed to connect to the X server while trying to get the supported video modes" << std::endl;
117     }
118 
119     return modes;
120 }
121 
122 
123 ////////////////////////////////////////////////////////////
getDesktopMode()124 VideoMode VideoModeImpl::getDesktopMode()
125 {
126     VideoMode desktopMode;
127 
128     // Open a connection with the X server
129     Display* display = OpenDisplay();
130     if (display)
131     {
132         // Retrieve the default screen number
133         int screen = DefaultScreen(display);
134 
135         // Check if the XRandR extension is present
136         int version;
137         if (XQueryExtension(display, "RANDR", &version, &version, &version))
138         {
139             // Get the current configuration
140             XRRScreenConfiguration* config = XRRGetScreenInfo(display, RootWindow(display, screen));
141             if (config)
142             {
143                 // Get the current video mode
144                 Rotation currentRotation;
145                 int currentMode = XRRConfigCurrentConfiguration(config, &currentRotation);
146 
147                 // Get the available screen sizes
148                 int nbSizes;
149                 XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes);
150                 if (sizes && (nbSizes > 0))
151                 {
152                     desktopMode = VideoMode(sizes[currentMode].width, sizes[currentMode].height, DefaultDepth(display, screen));
153 
154                     Rotation currentRotation;
155                     XRRConfigRotations(config, &currentRotation);
156 
157                     if (currentRotation == RR_Rotate_90 || currentRotation == RR_Rotate_270)
158                         std::swap(desktopMode.width, desktopMode.height);
159                 }
160 
161                 // Free the configuration instance
162                 XRRFreeScreenConfigInfo(config);
163             }
164             else
165             {
166                 // Failed to get the screen configuration
167                 err() << "Failed to retrieve the screen configuration while trying to get the desktop video modes" << std::endl;
168             }
169         }
170         else
171         {
172             // XRandr extension is not supported: we cannot get the video modes
173             err() << "Failed to use the XRandR extension while trying to get the desktop video modes" << std::endl;
174         }
175 
176         // Close the connection with the X server
177         CloseDisplay(display);
178     }
179     else
180     {
181         // We couldn't connect to the X server
182         err() << "Failed to connect to the X server while trying to get the desktop video modes" << std::endl;
183     }
184 
185     return desktopMode;
186 }
187 
188 } // namespace priv
189 
190 } // namespace sf
191