1 /////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/unix/displayx11.cpp 
   3 // Purpose:     Unix/X11 implementation of wxDisplay class 
   4 // Author:      Brian Victor, Vadim Zeitlin 
   8 // Copyright:   (c) wxWidgets team 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // For compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  29 #include "wx/display.h" 
  32     #include "wx/dynarray.h" 
  33     #include "wx/gdicmn.h" 
  34     #include "wx/string.h" 
  38 #endif /* WX_PRECOMP */ 
  40 #include "wx/display_impl.h" 
  42 /* These must be included after the wx files.  Otherwise the Data macro in 
  43  * Xlibint.h conflicts with a function declaration in wx/list.h.  */ 
  47     #include <X11/Xlibint.h> 
  49     #include <X11/extensions/Xinerama.h> 
  50     #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H 
  51         #include <X11/extensions/xf86vmode.h> 
  55 // ---------------------------------------------------------------------------- 
  56 // helper class to automatically free XineramaQueryScreens() return value 
  57 // ---------------------------------------------------------------------------- 
  64         m_screens 
= XineramaQueryScreens((Display 
*)wxGetDisplay(), &m_num
); 
  72     operator const XineramaScreenInfo 
*() const { return m_screens
; } 
  74     unsigned GetCount() const { return wx_static_cast(unsigned, m_num
); } 
  77     XineramaScreenInfo 
*m_screens
; 
  81 // ---------------------------------------------------------------------------- 
  82 // display and display factory classes 
  83 // ---------------------------------------------------------------------------- 
  85 class WXDLLEXPORT wxDisplayImplX11 
: public wxDisplayImpl
 
  88     wxDisplayImplX11(unsigned n
, const XineramaScreenInfo
& info
) 
  90           m_rect(info
.x_org
, info
.y_org
, info
.width
, info
.height
) 
  94     virtual wxRect 
GetGeometry() const { return m_rect
; } 
  95     virtual wxRect 
GetClientArea() const 
  97         // we intentionally don't cache the result here because the client 
  98         // display area may change (e.g. the user resized or hid a panel) and 
  99         // we don't currently react to its changes 
 100         return IsPrimary() ? wxGetClientDisplayRect() : m_rect
; 
 103     virtual wxString 
GetName() const { return wxString(); } 
 105     virtual wxArrayVideoModes 
GetModes(const wxVideoMode
& mode
) const; 
 106     virtual wxVideoMode 
GetCurrentMode() const; 
 107     virtual bool ChangeMode(const wxVideoMode
& mode
); 
 113     DECLARE_NO_COPY_CLASS(wxDisplayImplX11
) 
 116 class wxDisplayFactoryX11 
: public wxDisplayFactory
 
 119     wxDisplayFactoryX11() { } 
 121     virtual wxDisplayImpl 
*CreateDisplay(unsigned n
); 
 122     virtual unsigned GetCount(); 
 123     virtual int GetFromPoint(const wxPoint
& pt
); 
 126     DECLARE_NO_COPY_CLASS(wxDisplayFactoryX11
) 
 129 // ============================================================================ 
 130 // wxDisplayFactoryX11 implementation 
 131 // ============================================================================ 
 133 unsigned wxDisplayFactoryX11::GetCount() 
 135     return ScreensInfo().GetCount(); 
 138 int wxDisplayFactoryX11::GetFromPoint(const wxPoint
& p
) 
 142     const unsigned numscreens(screens
.GetCount()); 
 143     for ( unsigned i 
= 0; i 
< numscreens
; ++i 
) 
 145         const XineramaScreenInfo
& s 
= screens
[i
]; 
 146         if ( p
.x 
>= s
.x_org 
&& p
.x 
< s
.x_org 
+ s
.width 
&& 
 147                 p
.y 
>= s
.y_org 
&& p
.y 
< s
.y_org 
+ s
.height 
) 
 156 wxDisplayImpl 
*wxDisplayFactoryX11::CreateDisplay(unsigned n
) 
 160     return n 
< screens
.GetCount() ? new wxDisplayImplX11(n
, screens
[n
]) : NULL
; 
 163 // ============================================================================ 
 164 // wxDisplayImplX11 implementation 
 165 // ============================================================================ 
 167 #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H 
 170 //  See (http://www.xfree86.org/4.2.0/XF86VidModeDeleteModeLine.3.html) for more 
 171 //  info about xf86 video mode extensions 
 174 //free private data common to x (usually s3) servers 
 175 #define wxClearXVM(vm)  if(vm.privsize) XFree(vm.c_private) 
 177 // Correct res rate from GLFW 
 178 #define wxCRR2(v,dc) (int) (((1000.0f * (float) dc) /*PIXELS PER SECOND */) / ((float) v.htotal * v.vtotal /*PIXELS PER FRAME*/) + 0.5f) 
 179 #define wxCRR(v) wxCRR2(v,v.dotclock) 
 180 #define wxCVM2(v, dc) wxVideoMode(v.hdisplay, v.vdisplay, DefaultDepth((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay())), wxCRR2(v,dc)) 
 181 #define wxCVM(v) wxCVM2(v, v.dotclock) 
 183 wxArrayVideoModes 
wxDisplayImplX11::GetModes(const wxVideoMode
& mode
) const 
 186     Display
* pDisplay 
= (Display
*) wxGetDisplay(); //default display 
 187     int nScreen 
= DefaultScreen(pDisplay
); //default screen of (default) display... 
 190     XF86VidModeModeInfo
** ppXModes
; //Enumerated Modes (Don't forget XFree() :)) 
 191     int nNumModes
; //Number of modes enumerated.... 
 193     wxArrayVideoModes Modes
; //modes to return... 
 195     if (XF86VidModeGetAllModeLines(pDisplay
, nScreen
, &nNumModes
, &ppXModes
) == TRUE
) 
 197         for (int i 
= 0; i 
< nNumModes
; ++i
) 
 199             if (mode 
== wxDefaultVideoMode 
|| //According to display.h All modes valid if dafault mode... 
 200                 mode
.Matches(wxCVM((*ppXModes
[i
]))) ) //...? 
 202                 Modes
.Add(wxCVM((*ppXModes
[i
]))); 
 204             wxClearXVM((*ppXModes
[i
])); 
 205         //  XFree(ppXModes[i]); //supposed to free? 
 211         wxLogSysError(_("Failed to enumerate video modes")); 
 217 wxVideoMode 
wxDisplayImplX11::GetCurrentMode() const 
 219   XF86VidModeModeLine VM
; 
 221   XF86VidModeGetModeLine((Display
*)wxGetDisplay(), DefaultScreen((Display
*)wxGetDisplay()), 
 224   return wxCVM2(VM
, nDotClock
); 
 227 bool wxDisplayImplX11::ChangeMode(const wxVideoMode
& mode
) 
 229     XF86VidModeModeInfo
** ppXModes
; //Enumerated Modes (Don't forget XFree() :)) 
 230     int nNumModes
; //Number of modes enumerated.... 
 232     if( !XF86VidModeGetAllModeLines((Display
*)wxGetDisplay(), DefaultScreen((Display
*)wxGetDisplay()), &nNumModes
, &ppXModes
) ) 
 234         wxLogSysError(_("Failed to change video mode")); 
 239     if (mode 
== wxDefaultVideoMode
) 
 241         bRet 
= XF86VidModeSwitchToMode((Display
*)wxGetDisplay(), DefaultScreen((Display
*)wxGetDisplay()), 
 242                      ppXModes
[0]) == TRUE
; 
 244         for (int i 
= 0; i 
< nNumModes
; ++i
) 
 246             wxClearXVM((*ppXModes
[i
])); 
 247         //  XFree(ppXModes[i]); //supposed to free? 
 252         for (int i 
= 0; i 
< nNumModes
; ++i
) 
 255                 ppXModes
[i
]->hdisplay 
== mode
.w 
&& 
 256                 ppXModes
[i
]->vdisplay 
== mode
.h 
&& 
 257                 wxCRR((*ppXModes
[i
])) == mode
.refresh
) 
 260                 bRet 
= XF86VidModeSwitchToMode((Display
*)wxGetDisplay(), DefaultScreen((Display
*)wxGetDisplay()), 
 261                          ppXModes
[i
]) == TRUE
; 
 263             wxClearXVM((*ppXModes
[i
])); 
 264         //  XFree(ppXModes[i]); //supposed to free? 
 274 #else // !HAVE_X11_EXTENSIONS_XF86VMODE_H 
 276 wxArrayVideoModes 
wxDisplayImplX11::GetModes(const wxVideoMode
& modeMatch
) const 
 279     int* depths 
= XListDepths((Display
*)wxGetDisplay(), 0, &count_return
); 
 280     wxArrayVideoModes modes
; 
 283         for ( int x 
= 0; x 
< count_return
; ++x 
) 
 285             wxVideoMode 
mode(m_rect
.GetWidth(), m_rect
.GetHeight(), depths
[x
]); 
 286             if ( mode
.Matches(modeMatch
) ) 
 288                 modes
.Add(modeMatch
); 
 297 wxVideoMode 
wxDisplayImplX11::GetCurrentMode() const 
 300     return wxVideoMode(); 
 303 bool wxDisplayImplX11::ChangeMode(const wxVideoMode
& WXUNUSED(mode
)) 
 309 #endif // !HAVE_X11_EXTENSIONS_XF86VMODE_H 
 311 // ============================================================================ 
 312 // wxDisplay::CreateFactory() 
 313 // ============================================================================ 
 315 /* static */ wxDisplayFactory 
*wxDisplay::CreateFactory() 
 317     if ( XineramaIsActive((Display
*)wxGetDisplay()) ) 
 319         return new wxDisplayFactoryX11
; 
 322     return new wxDisplayFactorySingle
; 
 325 #endif /* wxUSE_DISPLAY */ 
 327 #include "wx/utils.h" 
 331 void wxClientDisplayRect(int *x
, int *y
, int *width
, int *height
) 
 333     // TODO: don't hardcode display size 
 344 #else // !wxUSE_LIBHILDON 
 346 #include <X11/Xlib.h> 
 347 #include <X11/Xatom.h> 
 349 // TODO: make this a full-fledged class and move to a public header 
 353     wxX11Ptr(void *ptr 
= NULL
) : m_ptr(ptr
) { } 
 354     ~wxX11Ptr() { if ( m_ptr 
) XFree(m_ptr
); } 
 359     DECLARE_NO_COPY_CLASS(wxX11Ptr
) 
 362 // NB: this function is implemented using X11 and not GDK calls as it's shared 
 363 //     by wxGTK[12], wxX11 and wxMotif ports 
 364 void wxClientDisplayRect(int *x
, int *y
, int *width
, int *height
) 
 366     Display 
* const dpy 
= wxGetX11Display(); 
 367     wxCHECK_RET( dpy
, _T("can't be called before initializing the GUI") ); 
 369     const Atom atomWorkArea 
= XInternAtom(dpy
, "_NET_WORKAREA", True
); 
 372         long *workareas 
= NULL
; 
 373         unsigned long numItems
; 
 374         unsigned long bytesRemaining
; 
 378         if ( XGetWindowProperty
 
 381                 XDefaultRootWindow(dpy
), 
 383                 0,                          // offset of data to retrieve 
 384                 4,                          // number of items to retrieve 
 385                 False
,                      // don't delete property 
 386                 XA_CARDINAL
,                // type of the items to get 
 391                 (unsigned char **)&workareas
 
 392              ) == Success 
&& workareas 
) 
 394             wxX11Ptr 
x11ptr(workareas
); // ensure it will be freed 
 396             // check that we retrieved the property of the expected type and 
 397             // that we did get back 4 longs (32 is the format for long), as 
 399             if ( actualType 
!= XA_CARDINAL 
|| 
 403                 wxLogDebug(_T("XGetWindowProperty(\"_NET_WORKAREA\") failed")); 
 412                 *width 
= workareas
[2]; 
 414                 *height 
= workareas
[3]; 
 420     // if we get here, _NET_WORKAREA is not supported so return the entire 
 421     // screen size as fall back 
 426     wxDisplaySize(width
, height
); 
 429 #endif // wxUSE_LIBHILDON/!wxUSE_LIBHILDON