]> git.saurik.com Git - wxWidgets.git/blob - src/unix/displayx11.cpp
9c17ef7d2815344597bbfc289bf7f46134297eb4
[wxWidgets.git] / src / unix / displayx11.cpp
1 ///////////////////////////////////////////////////////////////////////////
2 // Name: src/unix/displayx11.cpp
3 // Purpose: Unix/X11 implementation of wxDisplay class
4 // Author: Brian Victor, Vadim Zeitlin
5 // Modified by:
6 // Created: 12/05/02
7 // RCS-ID: $Id$
8 // Copyright: (c) wxWidgets team
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #include "wx/display.h"
28 #include "wx/display_impl.h"
29 #include "wx/intl.h"
30 #include "wx/log.h"
31
32 #ifndef WX_PRECOMP
33 #include "wx/dynarray.h"
34 #include "wx/gdicmn.h"
35 #include "wx/string.h"
36 #include "wx/utils.h"
37 #endif /* WX_PRECOMP */
38
39 #if wxUSE_DISPLAY
40
41 /* These must be included after the wx files. Otherwise the Data macro in
42 * Xlibint.h conflicts with a function declaration in wx/list.h. */
43 extern "C"
44 {
45 #include <X11/Xlib.h>
46 #include <X11/Xlibint.h>
47
48 #include <X11/extensions/Xinerama.h>
49 #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
50 #include <X11/extensions/xf86vmode.h>
51 #endif
52 }
53
54 // ----------------------------------------------------------------------------
55 // helper class to automatically free XineramaQueryScreens() return value
56 // ----------------------------------------------------------------------------
57
58 class ScreensInfo
59 {
60 public:
61 ScreensInfo()
62 {
63 m_screens = XineramaQueryScreens((Display *)wxGetDisplay(), &m_num);
64 }
65
66 ~ScreensInfo()
67 {
68 XFree(m_screens);
69 }
70
71 operator const XineramaScreenInfo *() const { return m_screens; }
72
73 size_t GetCount() const { return wx_static_cast(size_t, m_num); }
74
75 private:
76 XineramaScreenInfo *m_screens;
77 int m_num;
78 };
79
80 // ----------------------------------------------------------------------------
81 // display and display factory classes
82 // ----------------------------------------------------------------------------
83
84 class WXDLLEXPORT wxDisplayImplX11 : public wxDisplayImpl
85 {
86 public:
87 wxDisplayImplX11(size_t n, const XineramaScreenInfo& info)
88 : wxDisplayImpl(n),
89 m_rect(info.x_org, info.y_org, info.width, info.height)
90 {
91 }
92
93 virtual wxRect GetGeometry() const { return m_rect; }
94 virtual wxString GetName() const { return wxString(); }
95
96 virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const;
97 virtual wxVideoMode GetCurrentMode() const;
98 virtual bool ChangeMode(const wxVideoMode& mode);
99
100 private:
101 wxRect m_rect;
102 int m_depth;
103
104 DECLARE_NO_COPY_CLASS(wxDisplayImplX11)
105 };
106
107 class wxDisplayFactoryX11 : public wxDisplayFactory
108 {
109 public:
110 wxDisplayFactoryX11();
111
112 virtual wxDisplayImpl *CreateDisplay(size_t n);
113 virtual size_t GetCount();
114 virtual int GetFromPoint(const wxPoint& pt);
115
116 protected:
117 DECLARE_NO_COPY_CLASS(wxDisplayFactoryX11)
118 };
119
120 // ============================================================================
121 // wxDisplayFactoryX11 implementation
122 // ============================================================================
123
124 size_t wxDisplayFactoryX11::GetCount()
125 {
126 return ScreensInfo().GetCount();
127 }
128
129 int wxDisplayFactoryX11::GetFromPoint(const wxPoint& p)
130 {
131 ScreensInfo screens;
132
133 const size_t numscreens(screens.GetCount());
134 for ( size_t i = 0; i < numscreens; ++i )
135 {
136 const XineramaScreenInfo& s = screens[i];
137 if ( p.x >= s.x_org && p.x < s.x_org + s.width &&
138 p.y >= s.y_org && p.y < s.y_org + s.height )
139 {
140 return i;
141 }
142 }
143
144 return wxNOT_FOUND;
145 }
146
147 wxDisplayImpl *wxDisplayFactoryX11::CreateDisplay(size_t n)
148 {
149 ScreensInfo screens;
150
151 return n < screens.GetCount() ? new wxDisplayImplX11(n, screens[n]) : NULL;
152 }
153
154 // ============================================================================
155 // wxDisplayImplX11 implementation
156 // ============================================================================
157
158 #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
159
160 //
161 // See (http://www.xfree86.org/4.2.0/XF86VidModeDeleteModeLine.3.html) for more
162 // info about xf86 video mode extensions
163 //
164
165 //free private data common to x (usually s3) servers
166 #define wxClearXVM(vm) if(vm.privsize) XFree(vm.c_private)
167
168 // Correct res rate from GLFW
169 #define wxCRR2(v,dc) (int) (((1000.0f * (float) dc) /*PIXELS PER SECOND */) / ((float) v.htotal * v.vtotal /*PIXELS PER FRAME*/) + 0.5f)
170 #define wxCRR(v) wxCRR2(v,v.dotclock)
171 #define wxCVM2(v, dc) wxVideoMode(v.hdisplay, v.vdisplay, DefaultDepth((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay())), wxCRR2(v,dc))
172 #define wxCVM(v) wxCVM2(v, v.dotclock)
173
174 wxArrayVideoModes wxDisplayImplX11::GetModes(const wxVideoMode& mode) const
175 {
176 //Convenience...
177 Display* pDisplay = (Display*) wxGetDisplay(); //default display
178 int nScreen = DefaultScreen(pDisplay); //default screen of (default) display...
179
180 //Some variables..
181 XF86VidModeModeInfo** ppXModes; //Enumerated Modes (Don't forget XFree() :))
182 int nNumModes; //Number of modes enumerated....
183
184 wxArrayVideoModes Modes; //modes to return...
185
186 if (XF86VidModeGetAllModeLines(pDisplay, nScreen, &nNumModes, &ppXModes) == TRUE)
187 {
188 for (int i = 0; i < nNumModes; ++i)
189 {
190 if (mode == wxDefaultVideoMode || //According to display.h All modes valid if dafault mode...
191 mode.Matches(wxCVM((*ppXModes[i]))) ) //...?
192 {
193 Modes.Add(wxCVM((*ppXModes[i])));
194 }
195 wxClearXVM((*ppXModes[i]));
196 // XFree(ppXModes[i]); //supposed to free?
197 }
198 XFree(ppXModes);
199 }
200 else //OOPS!
201 {
202 wxLogSysError(_("Failed to enumerate video modes"));
203 }
204
205 return Modes;
206 }
207
208 wxVideoMode wxDisplayImplX11::GetCurrentMode() const
209 {
210 XF86VidModeModeLine VM;
211 int nDotClock;
212 XF86VidModeGetModeLine((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay()),
213 &nDotClock, &VM);
214 wxClearXVM(VM);
215 return wxCVM2(VM, nDotClock);
216 }
217
218 bool wxDisplayImplX11::ChangeMode(const wxVideoMode& mode)
219 {
220 XF86VidModeModeInfo** ppXModes; //Enumerated Modes (Don't forget XFree() :))
221 int nNumModes; //Number of modes enumerated....
222
223 if( !XF86VidModeGetAllModeLines((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay()), &nNumModes, &ppXModes) )
224 {
225 wxLogSysError(_("Failed to change video mode"));
226 return false;
227 }
228
229 bool bRet = false;
230 if (mode == wxDefaultVideoMode)
231 {
232 bRet = XF86VidModeSwitchToMode((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay()),
233 ppXModes[0]) == TRUE;
234
235 for (int i = 0; i < nNumModes; ++i)
236 {
237 wxClearXVM((*ppXModes[i]));
238 // XFree(ppXModes[i]); //supposed to free?
239 }
240 }
241 else
242 {
243 for (int i = 0; i < nNumModes; ++i)
244 {
245 if (!bRet &&
246 ppXModes[i]->hdisplay == mode.w &&
247 ppXModes[i]->vdisplay == mode.h &&
248 wxCRR((*ppXModes[i])) == mode.refresh)
249 {
250 //switch!
251 bRet = XF86VidModeSwitchToMode((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay()),
252 ppXModes[i]) == TRUE;
253 }
254 wxClearXVM((*ppXModes[i]));
255 // XFree(ppXModes[i]); //supposed to free?
256 }
257 }
258
259 XFree(ppXModes);
260
261 return bRet;
262 }
263
264
265 #else // !HAVE_X11_EXTENSIONS_XF86VMODE_H
266
267 wxArrayVideoModes wxDisplayImplX11::GetModes(const wxVideoMode& mode) const
268 {
269 int count_return;
270 int* depths = XListDepths((Display*)wxGetDisplay(), 0, &count_return);
271 wxArrayVideoModes modes;
272 if ( depths )
273 {
274 for ( int x = 0; x < count_return; ++x )
275 {
276 modes.Add(wxVideoMode(m_rect.GetWidth(), m_rect.GetHeight(), depths[x]));
277 }
278
279 XFree(depths);
280 }
281 return modes;
282 }
283
284 wxVideoMode wxDisplayImplX11::GetCurrentMode() const
285 {
286 // Not implemented
287 return wxVideoMode();
288 }
289
290 bool wxDisplayImplX11::ChangeMode(const wxVideoMode& mode)
291 {
292 // Not implemented
293 return false;
294 }
295
296 #endif // !HAVE_X11_EXTENSIONS_XF86VMODE_H
297
298 // ============================================================================
299 // wxDisplay::CreateFactory()
300 // ============================================================================
301
302 /* static */ wxDisplayFactory *wxDisplay::CreateFactory()
303 {
304 if ( XineramaIsActive((Display*)wxGetDisplay()) )
305 {
306 return new wxDisplayFactoryX11;
307 }
308
309 return new wxDisplayFactorySingle;
310 }
311
312 #endif /* wxUSE_DISPLAY */