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