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" 
  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 
  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.  */ 
  62         #include <X11/Xlibint.h> 
  64         #include <X11/extensions/Xinerama.h> 
  67     typedef XineramaScreenInfo ScreenInfo
; 
  68 #endif // GTK+/Xinerama 
  70 // ---------------------------------------------------------------------------- 
  71 // helper class storing information about all screens 
  72 // ---------------------------------------------------------------------------- 
  74 // the base class provides access to ScreenInfo array, derived class 
  75 // initializes it using either GTK+ or Xinerama functions 
  79     operator const ScreenInfo 
*() const { return m_screens
; } 
  81     unsigned GetCount() const { return static_cast<unsigned>(m_num
); } 
  84     ScreenInfo 
*m_screens
; 
  90 class ScreensInfo 
: public ScreensInfoBase
 
  95         GdkScreen 
* const screen 
= gdk_screen_get_default(); 
  97         m_num 
= gdk_screen_get_n_monitors(screen
); 
  98         m_screens 
= new ScreenInfo
[m_num
]; 
  99         for ( int i 
= 0; i 
< m_num
; i
++ ) 
 102             gdk_screen_get_monitor_geometry(screen
, i
, &rect
); 
 103             m_screens
[i
].x_org 
= rect
.x
; 
 104             m_screens
[i
].y_org 
= rect
.y
; 
 105             m_screens
[i
].width 
= rect
.width
; 
 106             m_screens
[i
].height 
= rect
.height
; 
 118 class ScreensInfo 
: public ScreensInfoBase
 
 123         m_screens 
= XineramaQueryScreens((Display 
*)wxGetDisplay(), &m_num
); 
 132 #endif // GTK+/Xinerama 
 134 // ---------------------------------------------------------------------------- 
 135 // display and display factory classes 
 136 // ---------------------------------------------------------------------------- 
 138 class WXDLLEXPORT wxDisplayImplX11 
: public wxDisplayImpl
 
 141     wxDisplayImplX11(unsigned n
, const ScreenInfo
& info
) 
 143           m_rect(info
.x_org
, info
.y_org
, info
.width
, info
.height
) 
 147     virtual wxRect 
GetGeometry() const { return m_rect
; } 
 148     virtual wxRect 
GetClientArea() const 
 150         // we intentionally don't cache the result here because the client 
 151         // display area may change (e.g. the user resized or hid a panel) and 
 152         // we don't currently react to its changes 
 153         return IsPrimary() ? wxGetClientDisplayRect() : m_rect
; 
 156     virtual wxString 
GetName() const { return wxString(); } 
 158     virtual wxArrayVideoModes 
GetModes(const wxVideoMode
& mode
) const; 
 159     virtual wxVideoMode 
GetCurrentMode() const; 
 160     virtual bool ChangeMode(const wxVideoMode
& mode
); 
 166     wxDECLARE_NO_COPY_CLASS(wxDisplayImplX11
); 
 169 class wxDisplayFactoryX11 
: public wxDisplayFactory
 
 172     wxDisplayFactoryX11() { } 
 174     virtual wxDisplayImpl 
*CreateDisplay(unsigned n
); 
 175     virtual unsigned GetCount(); 
 176     virtual int GetFromPoint(const wxPoint
& pt
); 
 179     wxDECLARE_NO_COPY_CLASS(wxDisplayFactoryX11
); 
 182 // ============================================================================ 
 183 // wxDisplayFactoryX11 implementation 
 184 // ============================================================================ 
 186 unsigned wxDisplayFactoryX11::GetCount() 
 188     return ScreensInfo().GetCount(); 
 191 int wxDisplayFactoryX11::GetFromPoint(const wxPoint
& p
) 
 195     const unsigned numscreens(screens
.GetCount()); 
 196     for ( unsigned i 
= 0; i 
< numscreens
; ++i 
) 
 198         const ScreenInfo
& s 
= screens
[i
]; 
 199         if ( p
.x 
>= s
.x_org 
&& p
.x 
< s
.x_org 
+ s
.width 
&& 
 200                 p
.y 
>= s
.y_org 
&& p
.y 
< s
.y_org 
+ s
.height 
) 
 209 wxDisplayImpl 
*wxDisplayFactoryX11::CreateDisplay(unsigned n
) 
 213     return n 
< screens
.GetCount() ? new wxDisplayImplX11(n
, screens
[n
]) : NULL
; 
 216 // ============================================================================ 
 217 // wxDisplayImplX11 implementation 
 218 // ============================================================================ 
 220 #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H 
 222 #include <X11/extensions/xf86vmode.h> 
 225 //  See (http://www.xfree86.org/4.2.0/XF86VidModeDeleteModeLine.3.html) for more 
 226 //  info about xf86 video mode extensions 
 229 //free private data common to x (usually s3) servers 
 230 #define wxClearXVM(vm)  if(vm.privsize) XFree(vm.c_private) 
 232 // Correct res rate from GLFW 
 233 #define wxCRR2(v,dc) (int) (((1000.0f * (float) dc) /*PIXELS PER SECOND */) / ((float) v.htotal * v.vtotal /*PIXELS PER FRAME*/) + 0.5f) 
 234 #define wxCRR(v) wxCRR2(v,v.dotclock) 
 235 #define wxCVM2(v, dc) wxVideoMode(v.hdisplay, v.vdisplay, DefaultDepth((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay())), wxCRR2(v,dc)) 
 236 #define wxCVM(v) wxCVM2(v, v.dotclock) 
 238 wxArrayVideoModes 
wxDisplayImplX11::GetModes(const wxVideoMode
& mode
) const 
 241     Display
* pDisplay 
= (Display
*) wxGetDisplay(); //default display 
 242     int nScreen 
= DefaultScreen(pDisplay
); //default screen of (default) display... 
 245     XF86VidModeModeInfo
** ppXModes
; //Enumerated Modes (Don't forget XFree() :)) 
 246     int nNumModes
; //Number of modes enumerated.... 
 248     wxArrayVideoModes Modes
; //modes to return... 
 250     if (XF86VidModeGetAllModeLines(pDisplay
, nScreen
, &nNumModes
, &ppXModes
) == TRUE
) 
 252         for (int i 
= 0; i 
< nNumModes
; ++i
) 
 254             if (mode 
== wxDefaultVideoMode 
|| //According to display.h All modes valid if dafault mode... 
 255                 mode
.Matches(wxCVM((*ppXModes
[i
]))) ) //...? 
 257                 Modes
.Add(wxCVM((*ppXModes
[i
]))); 
 259             wxClearXVM((*ppXModes
[i
])); 
 260         //  XFree(ppXModes[i]); //supposed to free? 
 266         wxLogSysError(_("Failed to enumerate video modes")); 
 272 wxVideoMode 
wxDisplayImplX11::GetCurrentMode() const 
 274   XF86VidModeModeLine VM
; 
 276   XF86VidModeGetModeLine((Display
*)wxGetDisplay(), DefaultScreen((Display
*)wxGetDisplay()), 
 279   return wxCVM2(VM
, nDotClock
); 
 282 bool wxDisplayImplX11::ChangeMode(const wxVideoMode
& mode
) 
 284     XF86VidModeModeInfo
** ppXModes
; //Enumerated Modes (Don't forget XFree() :)) 
 285     int nNumModes
; //Number of modes enumerated.... 
 287     if( !XF86VidModeGetAllModeLines((Display
*)wxGetDisplay(), DefaultScreen((Display
*)wxGetDisplay()), &nNumModes
, &ppXModes
) ) 
 289         wxLogSysError(_("Failed to change video mode")); 
 294     if (mode 
== wxDefaultVideoMode
) 
 296         bRet 
= XF86VidModeSwitchToMode((Display
*)wxGetDisplay(), DefaultScreen((Display
*)wxGetDisplay()), 
 297                      ppXModes
[0]) == TRUE
; 
 299         for (int i 
= 0; i 
< nNumModes
; ++i
) 
 301             wxClearXVM((*ppXModes
[i
])); 
 302         //  XFree(ppXModes[i]); //supposed to free? 
 307         for (int i 
= 0; i 
< nNumModes
; ++i
) 
 310                 ppXModes
[i
]->hdisplay 
== mode
.GetWidth() && 
 311                 ppXModes
[i
]->vdisplay 
== mode
.GetHeight() && 
 312                 wxCRR((*ppXModes
[i
])) == mode
.GetRefresh()) 
 315                 bRet 
= XF86VidModeSwitchToMode((Display
*)wxGetDisplay(), DefaultScreen((Display
*)wxGetDisplay()), 
 316                          ppXModes
[i
]) == TRUE
; 
 318             wxClearXVM((*ppXModes
[i
])); 
 319         //  XFree(ppXModes[i]); //supposed to free? 
 329 #else // !HAVE_X11_EXTENSIONS_XF86VMODE_H 
 331 wxArrayVideoModes 
wxDisplayImplX11::GetModes(const wxVideoMode
& modeMatch
) const 
 334     int* depths 
= XListDepths((Display
*)wxGetDisplay(), 0, &count_return
); 
 335     wxArrayVideoModes modes
; 
 338         for ( int x 
= 0; x 
< count_return
; ++x 
) 
 340             wxVideoMode 
mode(m_rect
.GetWidth(), m_rect
.GetHeight(), depths
[x
]); 
 341             if ( mode
.Matches(modeMatch
) ) 
 343                 modes
.Add(modeMatch
); 
 352 wxVideoMode 
wxDisplayImplX11::GetCurrentMode() const 
 355     return wxVideoMode(); 
 358 bool wxDisplayImplX11::ChangeMode(const wxVideoMode
& WXUNUSED(mode
)) 
 364 #endif // !HAVE_X11_EXTENSIONS_XF86VMODE_H 
 366 // ============================================================================ 
 367 // wxDisplay::CreateFactory() 
 368 // ============================================================================ 
 370 /* static */ wxDisplayFactory 
*wxDisplay::CreateFactory() 
 372     // GTK+ screen functions are always available, no need to check for them 
 374     if ( !XineramaIsActive((Display
*)wxGetDisplay()) ) 
 375         return new wxDisplayFactorySingle
; 
 378     return new wxDisplayFactoryX11
; 
 381 #endif /* wxUSE_DISPLAY */ 
 383 #include "wx/utils.h" 
 385 #if wxUSE_LIBHILDON || wxUSE_LIBHILDON2 
 387 void wxClientDisplayRect(int *x
, int *y
, int *width
, int *height
) 
 389     // TODO: don't hardcode display size 
 400 #else // !wxUSE_LIBHILDON || !wxUSE_LIBHILDON2 
 404 #include <X11/Xlib.h> 
 405 #include <X11/Xatom.h> 
 407 // TODO: make this a full-fledged class and move to a public header 
 411     wxX11Ptr(void *ptr 
= NULL
) : m_ptr(ptr
) { } 
 412     ~wxX11Ptr() { if ( m_ptr 
) XFree(m_ptr
); } 
 417     wxDECLARE_NO_COPY_CLASS(wxX11Ptr
); 
 420 // NB: this function is implemented using X11 and not GDK calls as it's shared 
 421 //     by wxGTK[12], wxX11 and wxMotif ports 
 422 void wxClientDisplayRect(int *x
, int *y
, int *width
, int *height
) 
 424     Display 
* const dpy 
= wxGetX11Display(); 
 425     wxCHECK_RET( dpy
, wxT("can't be called before initializing the GUI") ); 
 427     const Atom atomWorkArea 
= XInternAtom(dpy
, "_NET_WORKAREA", True
); 
 430         long *workareas 
= NULL
; 
 431         unsigned long numItems
; 
 432         unsigned long bytesRemaining
; 
 436         if ( XGetWindowProperty
 
 439                 XDefaultRootWindow(dpy
), 
 441                 0,                          // offset of data to retrieve 
 442                 4,                          // number of items to retrieve 
 443                 False
,                      // don't delete property 
 444                 XA_CARDINAL
,                // type of the items to get 
 449                 (unsigned char **)&workareas
 
 450              ) == Success 
&& workareas 
) 
 452             wxX11Ptr 
x11ptr(workareas
); // ensure it will be freed 
 454             // check that we retrieved the property of the expected type and 
 455             // that we did get back 4 longs (32 is the format for long), as 
 457             if ( actualType 
!= XA_CARDINAL 
|| 
 461                 wxLogDebug(wxT("XGetWindowProperty(\"_NET_WORKAREA\") failed")); 
 470                 *width 
= workareas
[2]; 
 472                 *height 
= workareas
[3]; 
 478     // if we get here, _NET_WORKAREA is not supported so return the entire 
 479     // screen size as fall back 
 484     wxDisplaySize(width
, height
); 
 487 #endif // wxUSE_LIBHILDON/!wxUSE_LIBHILDON