]> git.saurik.com Git - wxWidgets.git/blame - src/unix/displayx11.cpp
Remove non-working or semi-working tests added from console.cpp.
[wxWidgets.git] / src / unix / displayx11.cpp
CommitLineData
b1b3ddd8 1///////////////////////////////////////////////////////////////////////////
ef1717a9 2// Name: src/unix/displayx11.cpp
b1b3ddd8 3// Purpose: Unix/X11 implementation of wxDisplay class
ef1717a9 4// Author: Brian Victor, Vadim Zeitlin
b1b3ddd8
JS
5// Modified by:
6// Created: 12/05/02
7// RCS-ID: $Id$
77ffb593 8// Copyright: (c) wxWidgets team
65571936 9// Licence: wxWindows licence
b1b3ddd8
JS
10/////////////////////////////////////////////////////////////////////////////
11
ef1717a9
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
b1b3ddd8
JS
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
ad9835c9 24 #pragma hdrstop
b1b3ddd8
JS
25#endif
26
ad9835c9 27#if wxUSE_DISPLAY
b1b3ddd8 28
88a7a4e1
WS
29#include "wx/display.h"
30
b1b3ddd8 31#ifndef WX_PRECOMP
ad9835c9
WS
32 #include "wx/dynarray.h"
33 #include "wx/gdicmn.h"
34 #include "wx/string.h"
35 #include "wx/utils.h"
88a7a4e1 36 #include "wx/intl.h"
e4db172a 37 #include "wx/log.h"
b1b3ddd8
JS
38#endif /* WX_PRECOMP */
39
ad9835c9 40#include "wx/display_impl.h"
b1b3ddd8 41
bfd62c8c
VZ
42#ifdef __WXGTK20__
43 #include <gdk/gdk.h>
44 #include <gdk/gdkx.h>
45
46 // define the struct with the same fields as XineramaScreenInfo (except for
47 // screen number which we don't need) but which we can use without
48 // including Xinerama headers
49 struct ScreenInfo
50 {
51 short x_org;
52 short y_org;
53 short width;
54 short height;
55 };
56#else // use raw Xinerama functions
57 /* These must be included after the wx files. Otherwise the Data macro in
58 * Xlibint.h conflicts with a function declaration in wx/list.h. */
59 extern "C"
60 {
61 #include <X11/Xlib.h>
62 #include <X11/Xlibint.h>
b1b3ddd8 63
bfd62c8c
VZ
64 #include <X11/extensions/Xinerama.h>
65 #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
66 #include <X11/extensions/xf86vmode.h>
67 #endif
68 }
69
70 typedef XineramaScreenInfo ScreenInfo;
71#endif // GTK+/Xinerama
b1b3ddd8 72
ef1717a9 73// ----------------------------------------------------------------------------
bfd62c8c 74// helper class storing information about all screens
ef1717a9
VZ
75// ----------------------------------------------------------------------------
76
bfd62c8c
VZ
77// the base class provides access to ScreenInfo array, derived class
78// initializes it using either GTK+ or Xinerama functions
79class ScreensInfoBase
80{
81public:
82 operator const ScreenInfo *() const { return m_screens; }
83
84 unsigned GetCount() const { return static_cast<unsigned>(m_num); }
85
86protected:
87 ScreenInfo *m_screens;
88 int m_num;
89};
90
91#ifdef __WXGTK20__
92
93class ScreensInfo : public ScreensInfoBase
b1b3ddd8 94{
ef1717a9
VZ
95public:
96 ScreensInfo()
b1b3ddd8 97 {
bfd62c8c
VZ
98 GdkScreen * const screen = gdk_screen_get_default();
99
100 m_num = gdk_screen_get_n_monitors(screen);
101 m_screens = new ScreenInfo[m_num];
102 for ( int i = 0; i < m_num; i++ )
103 {
104 GdkRectangle rect;
105 gdk_screen_get_monitor_geometry(screen, i, &rect);
106 m_screens[i].x_org = rect.x;
107 m_screens[i].y_org = rect.y;
108 m_screens[i].width = rect.width;
109 m_screens[i].height = rect.height;
110 }
b1b3ddd8
JS
111 }
112
ef1717a9 113 ~ScreensInfo()
3cb98121 114 {
bfd62c8c 115 delete [] m_screens;
3cb98121 116 }
bfd62c8c 117};
3cb98121 118
bfd62c8c 119#else // Xinerama
ef1717a9 120
bfd62c8c
VZ
121class ScreensInfo : public ScreensInfoBase
122{
123public:
124 ScreensInfo()
125 {
126 m_screens = XineramaQueryScreens((Display *)wxGetDisplay(), &m_num);
127 }
ef1717a9 128
bfd62c8c
VZ
129 ~ScreensInfo()
130 {
131 XFree(m_screens);
132 }
ef1717a9
VZ
133};
134
bfd62c8c
VZ
135#endif // GTK+/Xinerama
136
ef1717a9
VZ
137// ----------------------------------------------------------------------------
138// display and display factory classes
139// ----------------------------------------------------------------------------
b1b3ddd8 140
ef1717a9 141class WXDLLEXPORT wxDisplayImplX11 : public wxDisplayImpl
b1b3ddd8 142{
ef1717a9 143public:
bfd62c8c 144 wxDisplayImplX11(unsigned n, const ScreenInfo& info)
547308b8
VZ
145 : wxDisplayImpl(n),
146 m_rect(info.x_org, info.y_org, info.width, info.height)
ef1717a9
VZ
147 {
148 }
b1b3ddd8 149
ef1717a9 150 virtual wxRect GetGeometry() const { return m_rect; }
676c8c1d
VZ
151 virtual wxRect GetClientArea() const
152 {
153 // we intentionally don't cache the result here because the client
154 // display area may change (e.g. the user resized or hid a panel) and
155 // we don't currently react to its changes
156 return IsPrimary() ? wxGetClientDisplayRect() : m_rect;
157 }
158
ef1717a9
VZ
159 virtual wxString GetName() const { return wxString(); }
160
161 virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const;
162 virtual wxVideoMode GetCurrentMode() const;
163 virtual bool ChangeMode(const wxVideoMode& mode);
164
165private:
166 wxRect m_rect;
167 int m_depth;
168
c0c133e1 169 wxDECLARE_NO_COPY_CLASS(wxDisplayImplX11);
ef1717a9
VZ
170};
171
172class wxDisplayFactoryX11 : public wxDisplayFactory
b1b3ddd8 173{
ef1717a9 174public:
1003169e 175 wxDisplayFactoryX11() { }
ef1717a9 176
4e675101
PC
177 virtual wxDisplayImpl *CreateDisplay(unsigned n);
178 virtual unsigned GetCount();
ef1717a9 179 virtual int GetFromPoint(const wxPoint& pt);
b1b3ddd8 180
ef1717a9 181protected:
c0c133e1 182 wxDECLARE_NO_COPY_CLASS(wxDisplayFactoryX11);
ef1717a9
VZ
183};
184
185// ============================================================================
186// wxDisplayFactoryX11 implementation
187// ============================================================================
188
4e675101 189unsigned wxDisplayFactoryX11::GetCount()
b1b3ddd8 190{
ef1717a9 191 return ScreensInfo().GetCount();
b1b3ddd8
JS
192}
193
ef1717a9 194int wxDisplayFactoryX11::GetFromPoint(const wxPoint& p)
b1b3ddd8 195{
ef1717a9
VZ
196 ScreensInfo screens;
197
4e675101
PC
198 const unsigned numscreens(screens.GetCount());
199 for ( unsigned i = 0; i < numscreens; ++i )
ef1717a9 200 {
bfd62c8c 201 const ScreenInfo& s = screens[i];
ef1717a9
VZ
202 if ( p.x >= s.x_org && p.x < s.x_org + s.width &&
203 p.y >= s.y_org && p.y < s.y_org + s.height )
204 {
205 return i;
206 }
207 }
208
209 return wxNOT_FOUND;
b1b3ddd8
JS
210}
211
4e675101 212wxDisplayImpl *wxDisplayFactoryX11::CreateDisplay(unsigned n)
b1b3ddd8 213{
ef1717a9
VZ
214 ScreensInfo screens;
215
547308b8 216 return n < screens.GetCount() ? new wxDisplayImplX11(n, screens[n]) : NULL;
b1b3ddd8
JS
217}
218
ef1717a9
VZ
219// ============================================================================
220// wxDisplayImplX11 implementation
221// ============================================================================
505c8ccd
VS
222
223#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
224
73b89f70
RN
225//
226// See (http://www.xfree86.org/4.2.0/XF86VidModeDeleteModeLine.3.html) for more
227// info about xf86 video mode extensions
228//
229
2980fc88
RN
230//free private data common to x (usually s3) servers
231#define wxClearXVM(vm) if(vm.privsize) XFree(vm.c_private)
232
a90bf709 233// Correct res rate from GLFW
2980fc88
RN
234#define wxCRR2(v,dc) (int) (((1000.0f * (float) dc) /*PIXELS PER SECOND */) / ((float) v.htotal * v.vtotal /*PIXELS PER FRAME*/) + 0.5f)
235#define wxCRR(v) wxCRR2(v,v.dotclock)
236#define wxCVM2(v, dc) wxVideoMode(v.hdisplay, v.vdisplay, DefaultDepth((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay())), wxCRR2(v,dc))
237#define wxCVM(v) wxCVM2(v, v.dotclock)
73b89f70 238
0d5b6a40 239wxArrayVideoModes wxDisplayImplX11::GetModes(const wxVideoMode& mode) const
e07d33e7 240{
73b89f70
RN
241 //Convenience...
242 Display* pDisplay = (Display*) wxGetDisplay(); //default display
243 int nScreen = DefaultScreen(pDisplay); //default screen of (default) display...
244
245 //Some variables..
246 XF86VidModeModeInfo** ppXModes; //Enumerated Modes (Don't forget XFree() :))
247 int nNumModes; //Number of modes enumerated....
248
249 wxArrayVideoModes Modes; //modes to return...
250
251 if (XF86VidModeGetAllModeLines(pDisplay, nScreen, &nNumModes, &ppXModes) == TRUE)
252 {
253 for (int i = 0; i < nNumModes; ++i)
254 {
255 if (mode == wxDefaultVideoMode || //According to display.h All modes valid if dafault mode...
2980fc88 256 mode.Matches(wxCVM((*ppXModes[i]))) ) //...?
73b89f70 257 {
2980fc88 258 Modes.Add(wxCVM((*ppXModes[i])));
73b89f70
RN
259 }
260 wxClearXVM((*ppXModes[i]));
261 // XFree(ppXModes[i]); //supposed to free?
262 }
263 XFree(ppXModes);
264 }
265 else //OOPS!
266 {
428b6942 267 wxLogSysError(_("Failed to enumerate video modes"));
73b89f70
RN
268 }
269
270 return Modes;
e07d33e7
RN
271}
272
0d5b6a40 273wxVideoMode wxDisplayImplX11::GetCurrentMode() const
e07d33e7 274{
2980fc88
RN
275 XF86VidModeModeLine VM;
276 int nDotClock;
277 XF86VidModeGetModeLine((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay()),
278 &nDotClock, &VM);
279 wxClearXVM(VM);
280 return wxCVM2(VM, nDotClock);
e07d33e7
RN
281}
282
0d5b6a40 283bool wxDisplayImplX11::ChangeMode(const wxVideoMode& mode)
e07d33e7 284{
a90bf709
VZ
285 XF86VidModeModeInfo** ppXModes; //Enumerated Modes (Don't forget XFree() :))
286 int nNumModes; //Number of modes enumerated....
287
288 if( !XF86VidModeGetAllModeLines((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay()), &nNumModes, &ppXModes) )
73b89f70 289 {
a90bf709
VZ
290 wxLogSysError(_("Failed to change video mode"));
291 return false;
292 }
73b89f70 293
a90bf709
VZ
294 bool bRet = false;
295 if (mode == wxDefaultVideoMode)
296 {
297 bRet = XF86VidModeSwitchToMode((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay()),
298 ppXModes[0]) == TRUE;
299
300 for (int i = 0; i < nNumModes; ++i)
73b89f70 301 {
a90bf709
VZ
302 wxClearXVM((*ppXModes[i]));
303 // XFree(ppXModes[i]); //supposed to free?
304 }
305 }
306 else
307 {
308 for (int i = 0; i < nNumModes; ++i)
309 {
310 if (!bRet &&
69fb24ce
RR
311 ppXModes[i]->hdisplay == mode.GetWidth() &&
312 ppXModes[i]->vdisplay == mode.GetHeight() &&
313 wxCRR((*ppXModes[i])) == mode.GetRefresh())
2980fc88 314 {
a90bf709 315 //switch!
2980fc88 316 bRet = XF86VidModeSwitchToMode((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay()),
a90bf709 317 ppXModes[i]) == TRUE;
2980fc88 318 }
a90bf709
VZ
319 wxClearXVM((*ppXModes[i]));
320 // XFree(ppXModes[i]); //supposed to free?
73b89f70
RN
321 }
322 }
a90bf709
VZ
323
324 XFree(ppXModes);
325
326 return bRet;
e5804ce7
RN
327}
328
329
330#else // !HAVE_X11_EXTENSIONS_XF86VMODE_H
331
d5a20ebb 332wxArrayVideoModes wxDisplayImplX11::GetModes(const wxVideoMode& modeMatch) const
e5804ce7 333{
ef1717a9
VZ
334 int count_return;
335 int* depths = XListDepths((Display*)wxGetDisplay(), 0, &count_return);
336 wxArrayVideoModes modes;
337 if ( depths )
f2ebd959 338 {
ef1717a9
VZ
339 for ( int x = 0; x < count_return; ++x )
340 {
d5a20ebb
VZ
341 wxVideoMode mode(m_rect.GetWidth(), m_rect.GetHeight(), depths[x]);
342 if ( mode.Matches(modeMatch) )
343 {
344 modes.Add(modeMatch);
345 }
ef1717a9
VZ
346 }
347
348 XFree(depths);
f2ebd959 349 }
ef1717a9 350 return modes;
505c8ccd
VS
351}
352
0d5b6a40 353wxVideoMode wxDisplayImplX11::GetCurrentMode() const
505c8ccd
VS
354{
355 // Not implemented
356 return wxVideoMode();
357}
358
d5a20ebb 359bool wxDisplayImplX11::ChangeMode(const wxVideoMode& WXUNUSED(mode))
505c8ccd
VS
360{
361 // Not implemented
362 return false;
363}
364
365#endif // !HAVE_X11_EXTENSIONS_XF86VMODE_H
366
ef1717a9
VZ
367// ============================================================================
368// wxDisplay::CreateFactory()
369// ============================================================================
370
371/* static */ wxDisplayFactory *wxDisplay::CreateFactory()
372{
bfd62c8c
VZ
373 // GTK+ screen functions are always available, no need to check for them
374#ifndef __WXGTK20__
375 if ( !XineramaIsActive((Display*)wxGetDisplay()) )
376 return new wxDisplayFactorySingle;
377#endif
ef1717a9 378
bfd62c8c 379 return new wxDisplayFactoryX11;
ef1717a9
VZ
380}
381
505c8ccd 382#endif /* wxUSE_DISPLAY */
676c8c1d
VZ
383
384#include "wx/utils.h"
385
426d19f1 386#if wxUSE_LIBHILDON || wxUSE_LIBHILDON2
66d05130
VZ
387
388void wxClientDisplayRect(int *x, int *y, int *width, int *height)
389{
390 // TODO: don't hardcode display size
391 if ( x )
392 *x = 0;
393 if ( y )
394 *y = 0;
395 if ( width )
396 *width = 672;
397 if ( height )
398 *height = 396;
399}
400
426d19f1 401#else // !wxUSE_LIBHILDON || !wxUSE_LIBHILDON2
66d05130 402
562e60a0
PC
403#include "wx/log.h"
404
64bd3204 405#include <X11/Xlib.h>
676c8c1d
VZ
406#include <X11/Xatom.h>
407
408// TODO: make this a full-fledged class and move to a public header
409class wxX11Ptr
410{
411public:
412 wxX11Ptr(void *ptr = NULL) : m_ptr(ptr) { }
413 ~wxX11Ptr() { if ( m_ptr ) XFree(m_ptr); }
414
415private:
416 void *m_ptr;
417
c0c133e1 418 wxDECLARE_NO_COPY_CLASS(wxX11Ptr);
676c8c1d
VZ
419};
420
421// NB: this function is implemented using X11 and not GDK calls as it's shared
422// by wxGTK[12], wxX11 and wxMotif ports
423void wxClientDisplayRect(int *x, int *y, int *width, int *height)
424{
425 Display * const dpy = wxGetX11Display();
9a83f860 426 wxCHECK_RET( dpy, wxT("can't be called before initializing the GUI") );
676c8c1d
VZ
427
428 const Atom atomWorkArea = XInternAtom(dpy, "_NET_WORKAREA", True);
429 if ( atomWorkArea )
430 {
431 long *workareas = NULL;
432 unsigned long numItems;
433 unsigned long bytesRemaining;
434 Atom actualType;
435 int format;
436
437 if ( XGetWindowProperty
438 (
439 dpy,
440 XDefaultRootWindow(dpy),
441 atomWorkArea,
442 0, // offset of data to retrieve
443 4, // number of items to retrieve
444 False, // don't delete property
445 XA_CARDINAL, // type of the items to get
446 &actualType,
447 &format,
448 &numItems,
449 &bytesRemaining,
450 (unsigned char **)&workareas
451 ) == Success && workareas )
452 {
453 wxX11Ptr x11ptr(workareas); // ensure it will be freed
454
f2633e54
VZ
455 // check that we retrieved the property of the expected type and
456 // that we did get back 4 longs (32 is the format for long), as
457 // requested
676c8c1d 458 if ( actualType != XA_CARDINAL ||
f2633e54 459 format != 32 ||
676c8c1d
VZ
460 numItems != 4 )
461 {
9a83f860 462 wxLogDebug(wxT("XGetWindowProperty(\"_NET_WORKAREA\") failed"));
676c8c1d
VZ
463 return;
464 }
465
466 if ( x )
467 *x = workareas[0];
468 if ( y )
469 *y = workareas[1];
470 if ( width )
471 *width = workareas[2];
472 if ( height )
473 *height = workareas[3];
474
475 return;
476 }
477 }
478
479 // if we get here, _NET_WORKAREA is not supported so return the entire
480 // screen size as fall back
481 if (x)
482 *x = 0;
483 if (y)
484 *y = 0;
485 wxDisplaySize(width, height);
486}
487
66d05130 488#endif // wxUSE_LIBHILDON/!wxUSE_LIBHILDON