1
///////////////////////////////////////////////////////////////////////////
2
// Name: src/unix/displayx11.cpp
3
// Purpose: Unix/X11 implementation of wxDisplay class
4
// Author: Brian Victor, Vadim Zeitlin
7
// Copyright: (c) wxWidgets team
8
// Licence: wxWindows licence
9
/////////////////////////////////////////////////////////////////////////////
11
// ============================================================================
13
// ============================================================================
15
// ----------------------------------------------------------------------------
17
// ----------------------------------------------------------------------------
19
// For compilers that support precompilation, includes "wx.h".
20
#include "wx/wxprec.h"
28
#include "wx/display.h"
31
#include "wx/dynarray.h"
32
#include "wx/gdicmn.h"
33
#include "wx/string.h"
37
#endif /* WX_PRECOMP */
39
#include "wx/display_impl.h"
45
// define the struct with the same fields as XineramaScreenInfo (except for
46
// screen number which we don't need) but which we can use without
47
// including Xinerama headers
55
#else // use raw Xinerama functions
56
/* These must be included after the wx files. Otherwise the Data macro in
57
* Xlibint.h conflicts with a function declaration in wx/list.h. */
61
#include <X11/Xlibint.h>
63
#include <X11/extensions/Xinerama.h>
66
typedef XineramaScreenInfo ScreenInfo;
67
#endif // GTK+/Xinerama
69
// ----------------------------------------------------------------------------
70
// helper class storing information about all screens
71
// ----------------------------------------------------------------------------
73
// the base class provides access to ScreenInfo array, derived class
74
// initializes it using either GTK+ or Xinerama functions
78
operator const ScreenInfo *() const { return m_screens; }
80
unsigned GetCount() const { return static_cast<unsigned>(m_num); }
83
ScreenInfo *m_screens;
89
class ScreensInfo : public ScreensInfoBase
94
GdkScreen * const screen = gdk_screen_get_default();
96
m_num = gdk_screen_get_n_monitors(screen);
97
m_screens = new ScreenInfo[m_num];
98
for ( int i = 0; i < m_num; i++ )
101
gdk_screen_get_monitor_geometry(screen, i, &rect);
102
m_screens[i].x_org = rect.x;
103
m_screens[i].y_org = rect.y;
104
m_screens[i].width = rect.width;
105
m_screens[i].height = rect.height;
117
class ScreensInfo : public ScreensInfoBase
122
m_screens = XineramaQueryScreens((Display *)wxGetDisplay(), &m_num);
131
#endif // GTK+/Xinerama
133
// ----------------------------------------------------------------------------
134
// display and display factory classes
135
// ----------------------------------------------------------------------------
137
class WXDLLEXPORT wxDisplayImplX11 : public wxDisplayImpl
140
wxDisplayImplX11(unsigned n, const ScreenInfo& info)
142
m_rect(info.x_org, info.y_org, info.width, info.height)
146
virtual wxRect GetGeometry() const { return m_rect; }
147
virtual wxRect GetClientArea() const
149
// we intentionally don't cache the result here because the client
150
// display area may change (e.g. the user resized or hid a panel) and
151
// we don't currently react to its changes
152
return IsPrimary() ? wxGetClientDisplayRect() : m_rect;
155
virtual wxString GetName() const { return wxString(); }
157
virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const;
158
virtual wxVideoMode GetCurrentMode() const;
159
virtual bool ChangeMode(const wxVideoMode& mode);
165
wxDECLARE_NO_COPY_CLASS(wxDisplayImplX11);
168
class wxDisplayFactoryX11 : public wxDisplayFactory
171
wxDisplayFactoryX11() { }
173
virtual wxDisplayImpl *CreateDisplay(unsigned n);
174
virtual unsigned GetCount();
175
virtual int GetFromPoint(const wxPoint& pt);
178
wxDECLARE_NO_COPY_CLASS(wxDisplayFactoryX11);
181
// ============================================================================
182
// wxDisplayFactoryX11 implementation
183
// ============================================================================
185
unsigned wxDisplayFactoryX11::GetCount()
187
return ScreensInfo().GetCount();
190
int wxDisplayFactoryX11::GetFromPoint(const wxPoint& p)
194
const unsigned numscreens(screens.GetCount());
195
for ( unsigned i = 0; i < numscreens; ++i )
197
const ScreenInfo& s = screens[i];
198
if ( p.x >= s.x_org && p.x < s.x_org + s.width &&
199
p.y >= s.y_org && p.y < s.y_org + s.height )
208
wxDisplayImpl *wxDisplayFactoryX11::CreateDisplay(unsigned n)
212
return n < screens.GetCount() ? new wxDisplayImplX11(n, screens[n]) : NULL;
215
// ============================================================================
216
// wxDisplayImplX11 implementation
217
// ============================================================================
219
#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
221
#include <X11/extensions/xf86vmode.h>
224
// See (http://www.xfree86.org/4.2.0/XF86VidModeDeleteModeLine.3.html) for more
225
// info about xf86 video mode extensions
228
//free private data common to x (usually s3) servers
229
#define wxClearXVM(vm) if(vm.privsize) XFree(vm.c_private)
231
// Correct res rate from GLFW
232
#define wxCRR2(v,dc) (int) (((1000.0f * (float) dc) /*PIXELS PER SECOND */) / ((float) v.htotal * v.vtotal /*PIXELS PER FRAME*/) + 0.5f)
233
#define wxCRR(v) wxCRR2(v,v.dotclock)
234
#define wxCVM2(v, dc) wxVideoMode(v.hdisplay, v.vdisplay, DefaultDepth((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay())), wxCRR2(v,dc))
235
#define wxCVM(v) wxCVM2(v, v.dotclock)
237
wxArrayVideoModes wxDisplayImplX11::GetModes(const wxVideoMode& mode) const
240
Display* pDisplay = (Display*) wxGetDisplay(); //default display
241
int nScreen = DefaultScreen(pDisplay); //default screen of (default) display...
244
XF86VidModeModeInfo** ppXModes; //Enumerated Modes (Don't forget XFree() :))
245
int nNumModes; //Number of modes enumerated....
247
wxArrayVideoModes Modes; //modes to return...
249
if (XF86VidModeGetAllModeLines(pDisplay, nScreen, &nNumModes, &ppXModes) == TRUE)
251
for (int i = 0; i < nNumModes; ++i)
253
if (mode == wxDefaultVideoMode || //According to display.h All modes valid if dafault mode...
254
mode.Matches(wxCVM((*ppXModes[i]))) ) //...?
256
Modes.Add(wxCVM((*ppXModes[i])));
258
wxClearXVM((*ppXModes[i]));
259
// XFree(ppXModes[i]); //supposed to free?
265
wxLogSysError(_("Failed to enumerate video modes"));
271
wxVideoMode wxDisplayImplX11::GetCurrentMode() const
273
XF86VidModeModeLine VM;
275
XF86VidModeGetModeLine((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay()),
278
return wxCVM2(VM, nDotClock);
281
bool wxDisplayImplX11::ChangeMode(const wxVideoMode& mode)
283
XF86VidModeModeInfo** ppXModes; //Enumerated Modes (Don't forget XFree() :))
284
int nNumModes; //Number of modes enumerated....
286
if( !XF86VidModeGetAllModeLines((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay()), &nNumModes, &ppXModes) )
288
wxLogSysError(_("Failed to change video mode"));
293
if (mode == wxDefaultVideoMode)
295
bRet = XF86VidModeSwitchToMode((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay()),
296
ppXModes[0]) == TRUE;
298
for (int i = 0; i < nNumModes; ++i)
300
wxClearXVM((*ppXModes[i]));
301
// XFree(ppXModes[i]); //supposed to free?
306
for (int i = 0; i < nNumModes; ++i)
309
ppXModes[i]->hdisplay == mode.GetWidth() &&
310
ppXModes[i]->vdisplay == mode.GetHeight() &&
311
wxCRR((*ppXModes[i])) == mode.GetRefresh())
314
bRet = XF86VidModeSwitchToMode((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay()),
315
ppXModes[i]) == TRUE;
317
wxClearXVM((*ppXModes[i]));
318
// XFree(ppXModes[i]); //supposed to free?
328
#else // !HAVE_X11_EXTENSIONS_XF86VMODE_H
330
wxArrayVideoModes wxDisplayImplX11::GetModes(const wxVideoMode& modeMatch) const
333
int* depths = XListDepths((Display*)wxGetDisplay(), 0, &count_return);
334
wxArrayVideoModes modes;
337
for ( int x = 0; x < count_return; ++x )
339
wxVideoMode mode(m_rect.GetWidth(), m_rect.GetHeight(), depths[x]);
340
if ( mode.Matches(modeMatch) )
342
modes.Add(modeMatch);
351
wxVideoMode wxDisplayImplX11::GetCurrentMode() const
354
return wxVideoMode();
357
bool wxDisplayImplX11::ChangeMode(const wxVideoMode& WXUNUSED(mode))
363
#endif // !HAVE_X11_EXTENSIONS_XF86VMODE_H
365
// ============================================================================
366
// wxDisplay::CreateFactory()
367
// ============================================================================
369
/* static */ wxDisplayFactory *wxDisplay::CreateFactory()
371
// GTK+ screen functions are always available, no need to check for them
373
if ( !XineramaIsActive((Display*)wxGetDisplay()) )
374
return new wxDisplayFactorySingle;
377
return new wxDisplayFactoryX11;
380
#endif /* wxUSE_DISPLAY */
382
#include "wx/utils.h"
384
#if wxUSE_LIBHILDON || wxUSE_LIBHILDON2 || !defined(GDK_WINDOWING_X11)
386
void wxClientDisplayRect(int *x, int *y, int *width, int *height)
388
// TODO: don't hardcode display size
399
#else // !wxUSE_LIBHILDON || !wxUSE_LIBHILDON2
403
#include <X11/Xlib.h>
404
#include <X11/Xatom.h>
406
// TODO: make this a full-fledged class and move to a public header
410
wxX11Ptr(void *ptr = NULL) : m_ptr(ptr) { }
411
~wxX11Ptr() { if ( m_ptr ) XFree(m_ptr); }
416
wxDECLARE_NO_COPY_CLASS(wxX11Ptr);
419
// NB: this function is implemented using X11 and not GDK calls as it's shared
420
// by wxGTK[12], wxX11 and wxMotif ports
421
void wxClientDisplayRect(int *x, int *y, int *width, int *height)
423
Display * const dpy = wxGetX11Display();
424
wxCHECK_RET( dpy, wxT("can't be called before initializing the GUI") );
428
const Atom atomWorkArea = XInternAtom(dpy, "_NET_WORKAREA", True);
431
long *workareas = NULL;
432
unsigned long numItems;
433
unsigned long bytesRemaining;
437
if ( XGetWindowProperty
440
XDefaultRootWindow(dpy),
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
450
(unsigned char **)&workareas
451
) == Success && workareas )
453
wxX11Ptr x11ptr(workareas); // ensure it will be freed
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
458
if ( actualType != XA_CARDINAL ||
462
wxLogDebug(wxT("XGetWindowProperty(\"_NET_WORKAREA\") failed"));
466
rectClient = wxRect(workareas[0], workareas[1],
467
workareas[2], workareas[3]);
472
// Although _NET_WORKAREA is supposed to return the client size of the
473
// screen, not all implementations are conforming, apparently, see #14419,
474
// so make sure we return a subset of the primary display.
478
const ScreenInfo& info = screens[0];
479
rectFull = wxRect(info.x_org, info.y_org, info.width, info.height);
481
wxDisplaySize(&rectFull.width, &rectFull.height);
484
if ( !rectClient.width || !rectClient.height )
486
// _NET_WORKAREA not available or didn't work, fall back to the total
488
rectClient = rectFull;
492
rectClient = rectClient.Intersect(rectFull);
500
*width = rectClient.width;
502
*height = rectClient.height;
505
#endif // wxUSE_LIBHILDON/!wxUSE_LIBHILDON