]> git.saurik.com Git - wxWidgets.git/blobdiff - src/unix/displayx11.cpp
add support for alpha in color dialog on OSX, see #14127
[wxWidgets.git] / src / unix / displayx11.cpp
index e74d3121634b17e62aeca34fb944ad5f8a28a686..fa51f6707ede050832f7787ca43e8c882ae49cd3 100644 (file)
 
 #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 <X11/Xlib.h>
-    #include <X11/Xlibint.h>
+#ifdef __WXGTK20__
+    #include <gdk/gdk.h>
+    #include <gdk/gdkx.h>
+
+    // 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 <X11/Xlib.h>
+        #include <X11/Xlibint.h>
 
-    #include <X11/extensions/Xinerama.h>
-    #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
-        #include <X11/extensions/xf86vmode.h>
-    #endif
-}
+        #include <X11/extensions/Xinerama.h>
+    }
+
+    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<unsigned>(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,7 +138,7 @@ 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)
     {
@@ -110,7 +163,7 @@ private:
     wxRect m_rect;
     int m_depth;
 
-    DECLARE_NO_COPY_CLASS(wxDisplayImplX11)
+    wxDECLARE_NO_COPY_CLASS(wxDisplayImplX11);
 };
 
 class wxDisplayFactoryX11 : public wxDisplayFactory
@@ -123,7 +176,7 @@ public:
     virtual int GetFromPoint(const wxPoint& pt);
 
 protected:
-    DECLARE_NO_COPY_CLASS(wxDisplayFactoryX11)
+    wxDECLARE_NO_COPY_CLASS(wxDisplayFactoryX11);
 };
 
 // ============================================================================
@@ -142,7 +195,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 )
         {
@@ -166,6 +219,8 @@ wxDisplayImpl *wxDisplayFactoryX11::CreateDisplay(unsigned n)
 
 #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
 
+#include <X11/extensions/xf86vmode.h>
+
 //
 //  See (http://www.xfree86.org/4.2.0/XF86VidModeDeleteModeLine.3.html) for more
 //  info about xf86 video mode extensions
@@ -252,9 +307,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()),
@@ -314,19 +369,20 @@ bool wxDisplayImplX11::ChangeMode(const wxVideoMode& WXUNUSED(mode))
 
 /* static */ wxDisplayFactory *wxDisplay::CreateFactory()
 {
-    if ( XineramaIsActive((Display*)wxGetDisplay()) )
-    {
-        return new wxDisplayFactoryX11;
-    }
+    // GTK+ screen functions are always available, no need to check for them
+#ifndef __WXGTK20__
+    if ( !XineramaIsActive((Display*)wxGetDisplay()) )
+        return new wxDisplayFactorySingle;
+#endif
 
-    return new wxDisplayFactorySingle;
+    return new wxDisplayFactoryX11;
 }
 
 #endif /* wxUSE_DISPLAY */
 
 #include "wx/utils.h"
 
-#if wxUSE_LIBHILDON
+#if wxUSE_LIBHILDON || wxUSE_LIBHILDON2 || !defined(GDK_WINDOWING_X11)
 
 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
 {
@@ -341,7 +397,7 @@ void wxClientDisplayRect(int *x, int *y, int *width, int *height)
         *height = 396;
 }
 
-#else // !wxUSE_LIBHILDON
+#else // !wxUSE_LIBHILDON || !wxUSE_LIBHILDON2
 
 #include "wx/log.h"
 
@@ -358,7 +414,7 @@ public:
 private:
     void *m_ptr;
 
-    DECLARE_NO_COPY_CLASS(wxX11Ptr)
+    wxDECLARE_NO_COPY_CLASS(wxX11Ptr);
 };
 
 // NB: this function is implemented using X11 and not GDK calls as it's shared
@@ -366,7 +422,9 @@ private:
 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
 {
     Display * const dpy = wxGetX11Display();
-    wxCHECK_RET( dpy, _T("can't be called before initializing the GUI") );
+    wxCHECK_RET( dpy, wxT("can't be called before initializing the GUI") );
+
+    wxRect rectClient;
 
     const Atom atomWorkArea = XInternAtom(dpy, "_NET_WORKAREA", True);
     if ( atomWorkArea )
@@ -402,30 +460,47 @@ void wxClientDisplayRect(int *x, int *y, int *width, int *height)
                     format != 32 ||
                         numItems != 4 )
             {
-                wxLogDebug(_T("XGetWindowProperty(\"_NET_WORKAREA\") failed"));
-                return;
+                wxLogDebug(wxT("XGetWindowProperty(\"_NET_WORKAREA\") failed"));
             }
+            else
+            {
+                rectClient = wxRect(workareas[0], workareas[1],
+                                    workareas[2], workareas[3]);
+            }
+        }
+    }
 
-            if ( x )
-                *x = workareas[0];
-            if ( y )
-                *y = workareas[1];
-            if ( width )
-                *width = workareas[2];
-            if ( height )
-                *height = 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
 
-            return;
-        }
+    if ( !rectClient.width || !rectClient.height )
+    {
+        // _NET_WORKAREA not available or didn't work, fall back to the total
+        // display size.
+        rectClient = rectFull;
+    }
+    else
+    {
+        rectClient = rectClient.Intersect(rectFull);
     }
 
-    // if we get here, _NET_WORKAREA is not supported so return the entire
-    // screen size as fall back
-    if (x)
-        *x = 0;
-    if (y)
-        *y = 0;
-    wxDisplaySize(width, height);
+    if ( x )
+        *x = rectClient.x;
+    if ( y )
+        *y = rectClient.y;
+    if ( width )
+        *width = rectClient.width;
+    if ( height )
+        *height = rectClient.height;
 }
 
 #endif // wxUSE_LIBHILDON/!wxUSE_LIBHILDON