X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4e675101a7fabdeaed5520257bf3dda457f54178..6ba718d7aee2f519d9146b90424ccec9e2243479:/src/unix/displayx11.cpp diff --git a/src/unix/displayx11.cpp b/src/unix/displayx11.cpp index f08b0bdcae..87dedfc530 100644 --- a/src/unix/displayx11.cpp +++ b/src/unix/displayx11.cpp @@ -4,7 +4,6 @@ // Author: Brian Victor, Vadim Zeitlin // Modified by: // Created: 12/05/02 -// RCS-ID: $Id$ // Copyright: (c) wxWidgets team // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -39,45 +38,98 @@ #include "wx/display_impl.h" -/* These must be included after the wx files. Otherwise the Data macro in - * Xlibint.h conflicts with a function declaration in wx/list.h. */ -extern "C" -{ - #include - #include +#ifdef __WXGTK20__ + #include + #include - #include - #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H - #include - #endif -} + // define the struct with the same fields as XineramaScreenInfo (except for + // screen number which we don't need) but which we can use without + // including Xinerama headers + struct ScreenInfo + { + short x_org; + short y_org; + short width; + short height; + }; +#else // use raw Xinerama functions + /* These must be included after the wx files. Otherwise the Data macro in + * Xlibint.h conflicts with a function declaration in wx/list.h. */ + extern "C" + { + #include + #include + + #include + } + + typedef XineramaScreenInfo ScreenInfo; +#endif // GTK+/Xinerama // ---------------------------------------------------------------------------- -// helper class to automatically free XineramaQueryScreens() return value +// helper class storing information about all screens // ---------------------------------------------------------------------------- -class ScreensInfo +// the base class provides access to ScreenInfo array, derived class +// initializes it using either GTK+ or Xinerama functions +class ScreensInfoBase +{ +public: + operator const ScreenInfo *() const { return m_screens; } + + unsigned GetCount() const { return static_cast(m_num); } + +protected: + ScreenInfo *m_screens; + int m_num; +}; + +#ifdef __WXGTK20__ + +class ScreensInfo : public ScreensInfoBase { public: ScreensInfo() { - m_screens = XineramaQueryScreens((Display *)wxGetDisplay(), &m_num); + GdkScreen * const screen = gdk_screen_get_default(); + + m_num = gdk_screen_get_n_monitors(screen); + m_screens = new ScreenInfo[m_num]; + for ( int i = 0; i < m_num; i++ ) + { + GdkRectangle rect; + gdk_screen_get_monitor_geometry(screen, i, &rect); + m_screens[i].x_org = rect.x; + m_screens[i].y_org = rect.y; + m_screens[i].width = rect.width; + m_screens[i].height = rect.height; + } } ~ScreensInfo() { - XFree(m_screens); + delete [] m_screens; } +}; - operator const XineramaScreenInfo *() const { return m_screens; } +#else // Xinerama - unsigned GetCount() const { return wx_static_cast(unsigned, m_num); } +class ScreensInfo : public ScreensInfoBase +{ +public: + ScreensInfo() + { + m_screens = XineramaQueryScreens((Display *)wxGetDisplay(), &m_num); + } -private: - XineramaScreenInfo *m_screens; - int m_num; + ~ScreensInfo() + { + XFree(m_screens); + } }; +#endif // GTK+/Xinerama + // ---------------------------------------------------------------------------- // display and display factory classes // ---------------------------------------------------------------------------- @@ -85,13 +137,21 @@ private: class WXDLLEXPORT wxDisplayImplX11 : public wxDisplayImpl { public: - wxDisplayImplX11(unsigned n, const XineramaScreenInfo& info) + wxDisplayImplX11(unsigned n, const ScreenInfo& info) : wxDisplayImpl(n), m_rect(info.x_org, info.y_org, info.width, info.height) { } virtual wxRect GetGeometry() const { return m_rect; } + virtual wxRect GetClientArea() const + { + // we intentionally don't cache the result here because the client + // display area may change (e.g. the user resized or hid a panel) and + // we don't currently react to its changes + return IsPrimary() ? wxGetClientDisplayRect() : m_rect; + } + virtual wxString GetName() const { return wxString(); } virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const; @@ -102,7 +162,7 @@ private: wxRect m_rect; int m_depth; - DECLARE_NO_COPY_CLASS(wxDisplayImplX11) + wxDECLARE_NO_COPY_CLASS(wxDisplayImplX11); }; class wxDisplayFactoryX11 : public wxDisplayFactory @@ -115,7 +175,7 @@ public: virtual int GetFromPoint(const wxPoint& pt); protected: - DECLARE_NO_COPY_CLASS(wxDisplayFactoryX11) + wxDECLARE_NO_COPY_CLASS(wxDisplayFactoryX11); }; // ============================================================================ @@ -134,7 +194,7 @@ int wxDisplayFactoryX11::GetFromPoint(const wxPoint& p) const unsigned numscreens(screens.GetCount()); for ( unsigned i = 0; i < numscreens; ++i ) { - const XineramaScreenInfo& s = screens[i]; + const ScreenInfo& s = screens[i]; if ( p.x >= s.x_org && p.x < s.x_org + s.width && p.y >= s.y_org && p.y < s.y_org + s.height ) { @@ -158,6 +218,8 @@ wxDisplayImpl *wxDisplayFactoryX11::CreateDisplay(unsigned n) #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H +#include + // // See (http://www.xfree86.org/4.2.0/XF86VidModeDeleteModeLine.3.html) for more // info about xf86 video mode extensions @@ -244,9 +306,9 @@ bool wxDisplayImplX11::ChangeMode(const wxVideoMode& mode) for (int i = 0; i < nNumModes; ++i) { if (!bRet && - ppXModes[i]->hdisplay == mode.w && - ppXModes[i]->vdisplay == mode.h && - wxCRR((*ppXModes[i])) == mode.refresh) + ppXModes[i]->hdisplay == mode.GetWidth() && + ppXModes[i]->vdisplay == mode.GetHeight() && + wxCRR((*ppXModes[i])) == mode.GetRefresh()) { //switch! bRet = XF86VidModeSwitchToMode((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay()), @@ -306,12 +368,138 @@ bool wxDisplayImplX11::ChangeMode(const wxVideoMode& WXUNUSED(mode)) /* static */ wxDisplayFactory *wxDisplay::CreateFactory() { - if ( XineramaIsActive((Display*)wxGetDisplay()) ) + // GTK+ screen functions are always available, no need to check for them +#ifndef __WXGTK20__ + if ( !XineramaIsActive((Display*)wxGetDisplay()) ) + return new wxDisplayFactorySingle; +#endif + + return new wxDisplayFactoryX11; +} + +#endif /* wxUSE_DISPLAY */ + +#include "wx/utils.h" + +#if wxUSE_LIBHILDON || wxUSE_LIBHILDON2 || !defined(GDK_WINDOWING_X11) + +void wxClientDisplayRect(int *x, int *y, int *width, int *height) +{ + // TODO: don't hardcode display size + if ( x ) + *x = 0; + if ( y ) + *y = 0; + if ( width ) + *width = 672; + if ( height ) + *height = 396; +} + +#else // !wxUSE_LIBHILDON || !wxUSE_LIBHILDON2 + +#include "wx/log.h" + +#include +#include + +// TODO: make this a full-fledged class and move to a public header +class wxX11Ptr +{ +public: + wxX11Ptr(void *ptr = NULL) : m_ptr(ptr) { } + ~wxX11Ptr() { if ( m_ptr ) XFree(m_ptr); } + +private: + void *m_ptr; + + wxDECLARE_NO_COPY_CLASS(wxX11Ptr); +}; + +// NB: this function is implemented using X11 and not GDK calls as it's shared +// by wxGTK[12], wxX11 and wxMotif ports +void wxClientDisplayRect(int *x, int *y, int *width, int *height) +{ + Display * const dpy = wxGetX11Display(); + wxCHECK_RET( dpy, wxT("can't be called before initializing the GUI") ); + + wxRect rectClient; + + const Atom atomWorkArea = XInternAtom(dpy, "_NET_WORKAREA", True); + if ( atomWorkArea ) + { + long *workareas = NULL; + unsigned long numItems; + unsigned long bytesRemaining; + Atom actualType; + int format; + + if ( XGetWindowProperty + ( + dpy, + XDefaultRootWindow(dpy), + atomWorkArea, + 0, // offset of data to retrieve + 4, // number of items to retrieve + False, // don't delete property + XA_CARDINAL, // type of the items to get + &actualType, + &format, + &numItems, + &bytesRemaining, + (unsigned char **)&workareas + ) == Success && workareas ) + { + wxX11Ptr x11ptr(workareas); // ensure it will be freed + + // check that we retrieved the property of the expected type and + // that we did get back 4 longs (32 is the format for long), as + // requested + if ( actualType != XA_CARDINAL || + format != 32 || + numItems != 4 ) + { + wxLogDebug(wxT("XGetWindowProperty(\"_NET_WORKAREA\") failed")); + } + else + { + rectClient = wxRect(workareas[0], workareas[1], + workareas[2], workareas[3]); + } + } + } + + // Although _NET_WORKAREA is supposed to return the client size of the + // screen, not all implementations are conforming, apparently, see #14419, + // so make sure we return a subset of the primary display. + wxRect rectFull; +#if wxUSE_DISPLAY + ScreensInfo screens; + const ScreenInfo& info = screens[0]; + rectFull = wxRect(info.x_org, info.y_org, info.width, info.height); +#else + wxDisplaySize(&rectFull.width, &rectFull.height); +#endif + + if ( !rectClient.width || !rectClient.height ) { - return new wxDisplayFactoryX11; + // _NET_WORKAREA not available or didn't work, fall back to the total + // display size. + rectClient = rectFull; + } + else + { + rectClient = rectClient.Intersect(rectFull); } - return new wxDisplayFactorySingle; + if ( x ) + *x = rectClient.x; + if ( y ) + *y = rectClient.y; + if ( width ) + *width = rectClient.width; + if ( height ) + *height = rectClient.height; } -#endif /* wxUSE_DISPLAY */ +#endif // wxUSE_LIBHILDON/!wxUSE_LIBHILDON