]> git.saurik.com Git - wxWidgets.git/commitdiff
applied wxGLApp patch (#464500)
authorVadim Zeitlin <vadim@wxwidgets.org>
Fri, 28 Sep 2001 13:53:55 +0000 (13:53 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Fri, 28 Sep 2001 13:53:55 +0000 (13:53 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@11716 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/gtk/app.h
include/wx/gtk/glcanvas.h
include/wx/gtk1/app.h
include/wx/gtk1/glcanvas.h
src/gtk/app.cpp
src/gtk/glcanvas.cpp
src/gtk1/app.cpp
src/gtk1/glcanvas.cpp

index 6014589623f641039958e07130c9b09d6f0d956b..2681dea2537e0eaf12f54f33bdfa71e27e34d1d9 100644 (file)
@@ -32,7 +32,7 @@ class wxApp: public wxAppBase
 {
 public:
     wxApp();
-    ~wxApp();
+    virtual ~wxApp();
 
     /* override for altering the way wxGTK intializes the GUI
      * (palette/visual/colorcube). under wxMSW, OnInitGui() does nothing by
@@ -75,6 +75,10 @@ public:
 #endif
     unsigned char  *m_colorCube;
 
+    // used by the the wxGLApp and wxGLCanvas class for GL-based X visual 
+    // selection; this is actually an XVisualInfo*
+    void           *m_glVisualInfo;
+    
 private:
     // true if we're inside an assert modal dialog
 #ifdef __WXDEBUG__
index 813e3147381437dd4e828f50c77d906760edbe6f..3eec4ab6ada4fd4d674ac632d2b2ffcc60d0800a 100644 (file)
 #ifndef _WX_GLCANVAS_H_
 #define _WX_GLCANVAS_H_
 
-#include <wx/defs.h>
+#include "wx/defs.h"
 
 #if wxUSE_GLCANVAS
 
-#include <wx/scrolwin.h>
+#include "wx/scrolwin.h"
+#include "wx/app.h"
 
 extern "C" {
-#include "GL/gl.h"
-#include "GL/glx.h"
-#include "GL/glu.h"
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <GL/glu.h>
 }
 
 //---------------------------------------------------------------------------
@@ -100,7 +101,7 @@ private:
 };
 
 //---------------------------------------------------------------------------
-// wxGLContext
+// wxGLCanvas
 //---------------------------------------------------------------------------
 
 class WXDLLEXPORT wxGLCanvas: public wxScrolledWindow
@@ -161,15 +162,43 @@ public:
     wxGLContext      *m_glContext,
                      *m_sharedContext;
     wxGLCanvas       *m_sharedContextOf;
-    void             *m_vi;
+    void             *m_vi; // actually an XVisualInfo*
+    bool              m_canFreeVi;
     GtkWidget        *m_glWidget;
     bool              m_exposed;
+    
+    // returns an XVisualInfo* based on desired GL attributes;
+    // returns NULL if an appropriate visual is not found. The
+    // caller is reponsible for using XFree() to deallocate 
+    // the returned structure.
+    static void* ChooseGLVisual(int *attribList);
 
 private:
     DECLARE_EVENT_TABLE()
     DECLARE_CLASS(wxGLCanvas)
 };
 
+
+//---------------------------------------------------------------------------
+// wxGLApp
+//---------------------------------------------------------------------------
+
+class WXDLLEXPORT wxGLApp: public wxApp
+{
+public:
+    wxGLApp() : wxApp() { }
+    ~wxGLApp();
+    
+    // use this in the constructor of the user-derived wxGLApp class to select
+    // an appropriate X visual for GL. Returns TRUE if an appropriate visual
+    // is found - and sets m_glVisualInfo; FALSE otherwise.
+    bool InitGLVisual(int *attribList);
+    
+private:
+    DECLARE_DYNAMIC_CLASS(wxGLApp)
+};
+
+
 #endif
     // wxUSE_GLCANVAS
 
index 6014589623f641039958e07130c9b09d6f0d956b..2681dea2537e0eaf12f54f33bdfa71e27e34d1d9 100644 (file)
@@ -32,7 +32,7 @@ class wxApp: public wxAppBase
 {
 public:
     wxApp();
-    ~wxApp();
+    virtual ~wxApp();
 
     /* override for altering the way wxGTK intializes the GUI
      * (palette/visual/colorcube). under wxMSW, OnInitGui() does nothing by
@@ -75,6 +75,10 @@ public:
 #endif
     unsigned char  *m_colorCube;
 
+    // used by the the wxGLApp and wxGLCanvas class for GL-based X visual 
+    // selection; this is actually an XVisualInfo*
+    void           *m_glVisualInfo;
+    
 private:
     // true if we're inside an assert modal dialog
 #ifdef __WXDEBUG__
index 813e3147381437dd4e828f50c77d906760edbe6f..3eec4ab6ada4fd4d674ac632d2b2ffcc60d0800a 100644 (file)
 #ifndef _WX_GLCANVAS_H_
 #define _WX_GLCANVAS_H_
 
-#include <wx/defs.h>
+#include "wx/defs.h"
 
 #if wxUSE_GLCANVAS
 
-#include <wx/scrolwin.h>
+#include "wx/scrolwin.h"
+#include "wx/app.h"
 
 extern "C" {
-#include "GL/gl.h"
-#include "GL/glx.h"
-#include "GL/glu.h"
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <GL/glu.h>
 }
 
 //---------------------------------------------------------------------------
@@ -100,7 +101,7 @@ private:
 };
 
 //---------------------------------------------------------------------------
-// wxGLContext
+// wxGLCanvas
 //---------------------------------------------------------------------------
 
 class WXDLLEXPORT wxGLCanvas: public wxScrolledWindow
@@ -161,15 +162,43 @@ public:
     wxGLContext      *m_glContext,
                      *m_sharedContext;
     wxGLCanvas       *m_sharedContextOf;
-    void             *m_vi;
+    void             *m_vi; // actually an XVisualInfo*
+    bool              m_canFreeVi;
     GtkWidget        *m_glWidget;
     bool              m_exposed;
+    
+    // returns an XVisualInfo* based on desired GL attributes;
+    // returns NULL if an appropriate visual is not found. The
+    // caller is reponsible for using XFree() to deallocate 
+    // the returned structure.
+    static void* ChooseGLVisual(int *attribList);
 
 private:
     DECLARE_EVENT_TABLE()
     DECLARE_CLASS(wxGLCanvas)
 };
 
+
+//---------------------------------------------------------------------------
+// wxGLApp
+//---------------------------------------------------------------------------
+
+class WXDLLEXPORT wxGLApp: public wxApp
+{
+public:
+    wxGLApp() : wxApp() { }
+    ~wxGLApp();
+    
+    // use this in the constructor of the user-derived wxGLApp class to select
+    // an appropriate X visual for GL. Returns TRUE if an appropriate visual
+    // is found - and sets m_glVisualInfo; FALSE otherwise.
+    bool InitGLVisual(int *attribList);
+    
+private:
+    DECLARE_DYNAMIC_CLASS(wxGLApp)
+};
+
+
 #endif
     // wxUSE_GLCANVAS
 
index 8502f2a279105cffa2b66fbd0fb0c1bf89d25247..38d4d1e75fdbd68a27c8c32b2d11363a342cabb1 100644 (file)
@@ -37,6 +37,7 @@
 #include <glib.h>
 #include <gdk/gdk.h>
 #include <gtk/gtk.h>
+#include <gdk/gdkx.h>
 
 #include "wx/gtk/win_gtk.h"
 
@@ -335,6 +336,9 @@ wxApp::wxApp()
 #endif
 
     m_colorCube = (unsigned char*) NULL;
+    
+    // this is NULL for a "regular" wxApp, but is set (and freed) by a wxGLApp
+    m_glVisualInfo = (void *) NULL;
 }
 
 wxApp::~wxApp()
@@ -355,11 +359,29 @@ bool wxApp::OnInitGui()
 
     GdkVisual *visual = gdk_visual_get_system();
 
+    // if this is a wxGLApp (derived from wxApp), and we've already
+    // chosen a specific visual, then derive the GdkVisual from that
+    if (m_glVisualInfo != NULL) {
+#ifdef __WXGTK20__
+        /* seems gtk_widget_set_default_visual no longer exists? */
+        GdkVisual* vis = gtk_widget_get_default_visual();
+#else
+        GdkVisual* vis = gdkx_visual_get( 
+            ((XVisualInfo *) m_glVisualInfo) ->visualid );
+        gtk_widget_set_default_visual( vis );
+#endif
+
+        GdkColormap *colormap = gdk_colormap_new( vis, FALSE );
+        gtk_widget_set_default_colormap( colormap );
+
+        visual = vis;
+    }
+    
     /* on some machines, the default visual is just 256 colours, so
        we make sure we get the best. this can sometimes be wasteful,
        of course, but what do these guys pay $30.000 for? */
 
-    if ((gdk_visual_get_best() != gdk_visual_get_system()) &&
+    else if ((gdk_visual_get_best() != gdk_visual_get_system()) &&
         (m_useBestVisual))
     {
 #ifdef __WXGTK20__
index a5ee3aa6bdbaacf9985b86583e8dedeb2079ec37..c15057112d81dd4a991232f6566f641f88029ba5 100644 (file)
@@ -283,7 +283,6 @@ bool wxGLCanvas::Create( wxWindow *parent,
                          int *attribList, 
                         const wxPalette& palette)
 {
-    int data[512];
     m_sharedContext = (wxGLContext*)shared;  // const_cast
     m_sharedContextOf = (wxGLCanvas*)shared_context_of;  // const_cast
     m_glContext = (wxGLContext*) NULL;
@@ -292,6 +291,68 @@ bool wxGLCanvas::Create( wxWindow *parent,
     m_noExpose = TRUE;
     m_nativeSizeEvent = TRUE;
     
+    XVisualInfo *vi = NULL;
+    if (wxTheApp->m_glVisualInfo != NULL) {
+        vi = (XVisualInfo *) wxTheApp->m_glVisualInfo; 
+        m_canFreeVi = FALSE; // owned by wxTheApp - don't free upon destruction
+    } else {
+        vi = (XVisualInfo *) ChooseGLVisual(attribList);
+        m_canFreeVi = TRUE;
+    }
+    m_vi = vi;  // save for later use
+    
+    wxCHECK_MSG( m_vi, FALSE, "required visual couldn't be found" );
+
+    GdkVisual *visual = gdkx_visual_get( vi->visualid );
+    GdkColormap *colormap = gdk_colormap_new( gdkx_visual_get(vi->visualid), TRUE );
+    
+    gtk_widget_push_colormap( colormap );
+    gtk_widget_push_visual( visual );
+
+    wxScrolledWindow::Create( parent, id, pos, size, style, name );
+
+    m_glWidget = m_wxwindow;
+    
+    gtk_pizza_set_clear( GTK_PIZZA(m_wxwindow), FALSE );
+    
+    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
+                            GTK_SIGNAL_FUNC(gtk_glwindow_realized_callback), (gpointer) this );
+
+    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "map",
+                            GTK_SIGNAL_FUNC(gtk_glwindow_map_callback), (gpointer) this );
+
+    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
+        GTK_SIGNAL_FUNC(gtk_glwindow_expose_callback), (gpointer)this );
+
+    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
+        GTK_SIGNAL_FUNC(gtk_glwindow_draw_callback), (gpointer)this );
+       
+    gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
+        GTK_SIGNAL_FUNC(gtk_glcanvas_size_callback), (gpointer)this );
+
+    gtk_widget_pop_visual();
+    gtk_widget_pop_colormap();
+    
+    if (GTK_WIDGET_REALIZED(m_wxwindow))
+        gtk_glwindow_realized_callback( m_wxwindow, this );
+    
+    if (GTK_WIDGET_MAPPED(m_wxwindow))
+        gtk_glwindow_map_callback( m_wxwindow, this );
+    
+    return TRUE;
+}
+
+wxGLCanvas::~wxGLCanvas()
+{
+    XVisualInfo *vi = (XVisualInfo *) m_vi;
+    
+    if (vi && m_canFreeVi) XFree( vi );
+    if (m_glContext) delete m_glContext;
+}
+
+void* wxGLCanvas::ChooseGLVisual(int *attribList)
+{
+    int data[512];
     if (!attribList)
     {
         // default settings if attriblist = 0
@@ -355,57 +416,7 @@ bool wxGLCanvas::Create( wxWindow *parent,
     
     Display *dpy = GDK_DISPLAY();
     
-    XVisualInfo *vi = glXChooseVisual( dpy, DefaultScreen(dpy), attribList );
-    
-    m_vi = vi;  // safe for later use
-    
-    wxCHECK_MSG( m_vi, FALSE, "required visual couldn't be found" );
-
-    GdkVisual *visual = gdkx_visual_get( vi->visualid );
-    GdkColormap *colormap = gdk_colormap_new( gdkx_visual_get(vi->visualid), TRUE );
-    
-    gtk_widget_push_colormap( colormap );
-    gtk_widget_push_visual( visual );
-
-    wxScrolledWindow::Create( parent, id, pos, size, style, name );
-
-    m_glWidget = m_wxwindow;
-    
-    gtk_pizza_set_clear( GTK_PIZZA(m_wxwindow), FALSE );
-    
-    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
-                            GTK_SIGNAL_FUNC(gtk_glwindow_realized_callback), (gpointer) this );
-
-    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "map",
-                            GTK_SIGNAL_FUNC(gtk_glwindow_map_callback), (gpointer) this );
-
-    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
-        GTK_SIGNAL_FUNC(gtk_glwindow_expose_callback), (gpointer)this );
-
-    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
-        GTK_SIGNAL_FUNC(gtk_glwindow_draw_callback), (gpointer)this );
-       
-    gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
-        GTK_SIGNAL_FUNC(gtk_glcanvas_size_callback), (gpointer)this );
-
-    gtk_widget_pop_visual();
-    gtk_widget_pop_colormap();
-    
-    if (GTK_WIDGET_REALIZED(m_wxwindow))
-        gtk_glwindow_realized_callback( m_wxwindow, this );
-    
-    if (GTK_WIDGET_MAPPED(m_wxwindow))
-        gtk_glwindow_map_callback( m_wxwindow, this );
-    
-    return TRUE;
-}
-
-wxGLCanvas::~wxGLCanvas()
-{
-    XVisualInfo *vi = (XVisualInfo *) m_vi;
-    
-    if (vi) XFree( vi );
-    if (m_glContext) delete m_glContext;
+    return glXChooseVisual( dpy, DefaultScreen(dpy), attribList );
 }
 
 void wxGLCanvas::SwapBuffers()
@@ -455,6 +466,26 @@ void wxGLCanvas::OnInternalIdle()
     wxWindow::OnInternalIdle();
 }
 
+
+
+//---------------------------------------------------------------------------
+// wxGLApp
+//---------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(wxGLApp, wxApp)
+        
+wxGLApp::~wxGLApp()
+{
+    if (m_glVisualInfo) XFree(m_glVisualInfo);
+}
+
+bool wxGLApp::InitGLVisual(int *attribList)
+{
+    if (m_glVisualInfo) XFree(m_glVisualInfo);
+    m_glVisualInfo = wxGLCanvas::ChooseGLVisual(attribList);
+    return (m_glVisualInfo != NULL);
+}
+
 #endif
     // wxUSE_GLCANVAS
 
index 8502f2a279105cffa2b66fbd0fb0c1bf89d25247..38d4d1e75fdbd68a27c8c32b2d11363a342cabb1 100644 (file)
@@ -37,6 +37,7 @@
 #include <glib.h>
 #include <gdk/gdk.h>
 #include <gtk/gtk.h>
+#include <gdk/gdkx.h>
 
 #include "wx/gtk/win_gtk.h"
 
@@ -335,6 +336,9 @@ wxApp::wxApp()
 #endif
 
     m_colorCube = (unsigned char*) NULL;
+    
+    // this is NULL for a "regular" wxApp, but is set (and freed) by a wxGLApp
+    m_glVisualInfo = (void *) NULL;
 }
 
 wxApp::~wxApp()
@@ -355,11 +359,29 @@ bool wxApp::OnInitGui()
 
     GdkVisual *visual = gdk_visual_get_system();
 
+    // if this is a wxGLApp (derived from wxApp), and we've already
+    // chosen a specific visual, then derive the GdkVisual from that
+    if (m_glVisualInfo != NULL) {
+#ifdef __WXGTK20__
+        /* seems gtk_widget_set_default_visual no longer exists? */
+        GdkVisual* vis = gtk_widget_get_default_visual();
+#else
+        GdkVisual* vis = gdkx_visual_get( 
+            ((XVisualInfo *) m_glVisualInfo) ->visualid );
+        gtk_widget_set_default_visual( vis );
+#endif
+
+        GdkColormap *colormap = gdk_colormap_new( vis, FALSE );
+        gtk_widget_set_default_colormap( colormap );
+
+        visual = vis;
+    }
+    
     /* on some machines, the default visual is just 256 colours, so
        we make sure we get the best. this can sometimes be wasteful,
        of course, but what do these guys pay $30.000 for? */
 
-    if ((gdk_visual_get_best() != gdk_visual_get_system()) &&
+    else if ((gdk_visual_get_best() != gdk_visual_get_system()) &&
         (m_useBestVisual))
     {
 #ifdef __WXGTK20__
index a5ee3aa6bdbaacf9985b86583e8dedeb2079ec37..c15057112d81dd4a991232f6566f641f88029ba5 100644 (file)
@@ -283,7 +283,6 @@ bool wxGLCanvas::Create( wxWindow *parent,
                          int *attribList, 
                         const wxPalette& palette)
 {
-    int data[512];
     m_sharedContext = (wxGLContext*)shared;  // const_cast
     m_sharedContextOf = (wxGLCanvas*)shared_context_of;  // const_cast
     m_glContext = (wxGLContext*) NULL;
@@ -292,6 +291,68 @@ bool wxGLCanvas::Create( wxWindow *parent,
     m_noExpose = TRUE;
     m_nativeSizeEvent = TRUE;
     
+    XVisualInfo *vi = NULL;
+    if (wxTheApp->m_glVisualInfo != NULL) {
+        vi = (XVisualInfo *) wxTheApp->m_glVisualInfo; 
+        m_canFreeVi = FALSE; // owned by wxTheApp - don't free upon destruction
+    } else {
+        vi = (XVisualInfo *) ChooseGLVisual(attribList);
+        m_canFreeVi = TRUE;
+    }
+    m_vi = vi;  // save for later use
+    
+    wxCHECK_MSG( m_vi, FALSE, "required visual couldn't be found" );
+
+    GdkVisual *visual = gdkx_visual_get( vi->visualid );
+    GdkColormap *colormap = gdk_colormap_new( gdkx_visual_get(vi->visualid), TRUE );
+    
+    gtk_widget_push_colormap( colormap );
+    gtk_widget_push_visual( visual );
+
+    wxScrolledWindow::Create( parent, id, pos, size, style, name );
+
+    m_glWidget = m_wxwindow;
+    
+    gtk_pizza_set_clear( GTK_PIZZA(m_wxwindow), FALSE );
+    
+    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
+                            GTK_SIGNAL_FUNC(gtk_glwindow_realized_callback), (gpointer) this );
+
+    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "map",
+                            GTK_SIGNAL_FUNC(gtk_glwindow_map_callback), (gpointer) this );
+
+    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
+        GTK_SIGNAL_FUNC(gtk_glwindow_expose_callback), (gpointer)this );
+
+    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
+        GTK_SIGNAL_FUNC(gtk_glwindow_draw_callback), (gpointer)this );
+       
+    gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
+        GTK_SIGNAL_FUNC(gtk_glcanvas_size_callback), (gpointer)this );
+
+    gtk_widget_pop_visual();
+    gtk_widget_pop_colormap();
+    
+    if (GTK_WIDGET_REALIZED(m_wxwindow))
+        gtk_glwindow_realized_callback( m_wxwindow, this );
+    
+    if (GTK_WIDGET_MAPPED(m_wxwindow))
+        gtk_glwindow_map_callback( m_wxwindow, this );
+    
+    return TRUE;
+}
+
+wxGLCanvas::~wxGLCanvas()
+{
+    XVisualInfo *vi = (XVisualInfo *) m_vi;
+    
+    if (vi && m_canFreeVi) XFree( vi );
+    if (m_glContext) delete m_glContext;
+}
+
+void* wxGLCanvas::ChooseGLVisual(int *attribList)
+{
+    int data[512];
     if (!attribList)
     {
         // default settings if attriblist = 0
@@ -355,57 +416,7 @@ bool wxGLCanvas::Create( wxWindow *parent,
     
     Display *dpy = GDK_DISPLAY();
     
-    XVisualInfo *vi = glXChooseVisual( dpy, DefaultScreen(dpy), attribList );
-    
-    m_vi = vi;  // safe for later use
-    
-    wxCHECK_MSG( m_vi, FALSE, "required visual couldn't be found" );
-
-    GdkVisual *visual = gdkx_visual_get( vi->visualid );
-    GdkColormap *colormap = gdk_colormap_new( gdkx_visual_get(vi->visualid), TRUE );
-    
-    gtk_widget_push_colormap( colormap );
-    gtk_widget_push_visual( visual );
-
-    wxScrolledWindow::Create( parent, id, pos, size, style, name );
-
-    m_glWidget = m_wxwindow;
-    
-    gtk_pizza_set_clear( GTK_PIZZA(m_wxwindow), FALSE );
-    
-    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
-                            GTK_SIGNAL_FUNC(gtk_glwindow_realized_callback), (gpointer) this );
-
-    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "map",
-                            GTK_SIGNAL_FUNC(gtk_glwindow_map_callback), (gpointer) this );
-
-    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
-        GTK_SIGNAL_FUNC(gtk_glwindow_expose_callback), (gpointer)this );
-
-    gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
-        GTK_SIGNAL_FUNC(gtk_glwindow_draw_callback), (gpointer)this );
-       
-    gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
-        GTK_SIGNAL_FUNC(gtk_glcanvas_size_callback), (gpointer)this );
-
-    gtk_widget_pop_visual();
-    gtk_widget_pop_colormap();
-    
-    if (GTK_WIDGET_REALIZED(m_wxwindow))
-        gtk_glwindow_realized_callback( m_wxwindow, this );
-    
-    if (GTK_WIDGET_MAPPED(m_wxwindow))
-        gtk_glwindow_map_callback( m_wxwindow, this );
-    
-    return TRUE;
-}
-
-wxGLCanvas::~wxGLCanvas()
-{
-    XVisualInfo *vi = (XVisualInfo *) m_vi;
-    
-    if (vi) XFree( vi );
-    if (m_glContext) delete m_glContext;
+    return glXChooseVisual( dpy, DefaultScreen(dpy), attribList );
 }
 
 void wxGLCanvas::SwapBuffers()
@@ -455,6 +466,26 @@ void wxGLCanvas::OnInternalIdle()
     wxWindow::OnInternalIdle();
 }
 
+
+
+//---------------------------------------------------------------------------
+// wxGLApp
+//---------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(wxGLApp, wxApp)
+        
+wxGLApp::~wxGLApp()
+{
+    if (m_glVisualInfo) XFree(m_glVisualInfo);
+}
+
+bool wxGLApp::InitGLVisual(int *attribList)
+{
+    if (m_glVisualInfo) XFree(m_glVisualInfo);
+    m_glVisualInfo = wxGLCanvas::ChooseGLVisual(attribList);
+    return (m_glVisualInfo != NULL);
+}
+
 #endif
     // wxUSE_GLCANVAS