]> git.saurik.com Git - wxWidgets.git/blobdiff - src/unix/displayx11.cpp
Don't crash in generic wxDataViewCtrl if selected column is removed.
[wxWidgets.git] / src / unix / displayx11.cpp
index 3f04ced7e5305913322e6a3dda5a74cbe813527b..04c5f86218d81035cfd8b57cc03e96fdc9dc4da8 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
 
-    size_t GetCount() const { return wx_static_cast(size_t, 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 +138,21 @@ private:
 class WXDLLEXPORT wxDisplayImplX11 : public wxDisplayImpl
 {
 public:
-    wxDisplayImplX11(size_t 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 +163,7 @@ private:
     wxRect m_rect;
     int m_depth;
 
-    DECLARE_NO_COPY_CLASS(wxDisplayImplX11)
+    wxDECLARE_NO_COPY_CLASS(wxDisplayImplX11);
 };
 
 class wxDisplayFactoryX11 : public wxDisplayFactory
@@ -110,19 +171,19 @@ class wxDisplayFactoryX11 : public wxDisplayFactory
 public:
     wxDisplayFactoryX11() { }
 
-    virtual wxDisplayImpl *CreateDisplay(size_t n);
-    virtual size_t GetCount();
+    virtual wxDisplayImpl *CreateDisplay(unsigned n);
+    virtual unsigned GetCount();
     virtual int GetFromPoint(const wxPoint& pt);
 
 protected:
-    DECLARE_NO_COPY_CLASS(wxDisplayFactoryX11)
+    wxDECLARE_NO_COPY_CLASS(wxDisplayFactoryX11);
 };
 
 // ============================================================================
 // wxDisplayFactoryX11 implementation
 // ============================================================================
 
-size_t wxDisplayFactoryX11::GetCount()
+unsigned wxDisplayFactoryX11::GetCount()
 {
     return ScreensInfo().GetCount();
 }
@@ -131,10 +192,10 @@ int wxDisplayFactoryX11::GetFromPoint(const wxPoint& p)
 {
     ScreensInfo screens;
 
-    const size_t numscreens(screens.GetCount());
-    for ( size_t i = 0; i < numscreens; ++i )
+    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 )
         {
@@ -145,7 +206,7 @@ int wxDisplayFactoryX11::GetFromPoint(const wxPoint& p)
     return wxNOT_FOUND;
 }
 
-wxDisplayImpl *wxDisplayFactoryX11::CreateDisplay(size_t n)
+wxDisplayImpl *wxDisplayFactoryX11::CreateDisplay(unsigned n)
 {
     ScreensInfo screens;
 
@@ -158,6 +219,8 @@ wxDisplayImpl *wxDisplayFactoryX11::CreateDisplay(size_t 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
@@ -244,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()),
@@ -306,12 +369,119 @@ 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
+
+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 <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+// 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") );
+
+    const Atom atomWorkArea = XInternAtom(dpy, "_NET_WORKAREA", True);
+    if ( atomWorkArea )
     {
-        return new wxDisplayFactoryX11;
+        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"));
+                return;
+            }
+
+            if ( x )
+                *x = workareas[0];
+            if ( y )
+                *y = workareas[1];
+            if ( width )
+                *width = workareas[2];
+            if ( height )
+                *height = workareas[3];
+
+            return;
+        }
     }
 
-    return new wxDisplayFactorySingle;
+    // 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);
 }
 
-#endif /* wxUSE_DISPLAY */
+#endif // wxUSE_LIBHILDON/!wxUSE_LIBHILDON