]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/glcanvas.cpp
correction to last commit: don't test unsetenv() return value, it's void under Darwin
[wxWidgets.git] / src / gtk / glcanvas.cpp
CommitLineData
8b089c5e 1/////////////////////////////////////////////////////////////////////////////
9b5f1895 2// Name: src/gtk/glcanvas.cpp
77ffb593 3// Purpose: wxGLCanvas, for using OpenGL/Mesa with wxWidgets and GTK
8b089c5e
JS
4// Author: Robert Roebling
5// Modified by:
6// Created: 17/08/98
7// RCS-ID: $Id$
8// Copyright: (c) Robert Roebling
65571936 9// Licence: wxWindows licence
8b089c5e
JS
10/////////////////////////////////////////////////////////////////////////////
11
14f355c2
VS
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
8b089c5e
JS
15#if wxUSE_GLCANVAS
16
17#include "wx/glcanvas.h"
18
670f9935
WS
19#ifndef WX_PRECOMP
20 #include "wx/app.h"
76b49cf4 21 #include "wx/frame.h"
7cf41a5d 22 #include "wx/colour.h"
02761f6c 23 #include "wx/module.h"
670f9935
WS
24#endif // WX_PRECOMP
25
a1abca32
PC
26#include <gtk/gtk.h>
27#include <gdk/gdkx.h>
8b089c5e
JS
28
29#include "wx/gtk/win_gtk.h"
30
dc3065a5
VZ
31#if WXWIN_COMPATIBILITY_2_8
32
8b089c5e 33//-----------------------------------------------------------------------------
dc3065a5 34// "realize" from m_wxwindow: used to create m_glContext implicitly
8b089c5e
JS
35//-----------------------------------------------------------------------------
36
865bb325 37extern "C" {
8b089c5e 38static gint
34a34b02 39gtk_glwindow_realized_callback( GtkWidget *WXUNUSED(widget), wxGLCanvas *win )
8b089c5e 40{
dc3065a5 41 win->GTKInitImplicitContext();
8b089c5e
JS
42
43 return FALSE;
44}
865bb325 45}
8b089c5e 46
dc3065a5
VZ
47#endif // WXWIN_COMPATIBILITY_2_8
48
8b089c5e
JS
49//-----------------------------------------------------------------------------
50// "map" from m_wxwindow
51//-----------------------------------------------------------------------------
52
865bb325 53extern "C" {
8b089c5e
JS
54static gint
55gtk_glwindow_map_callback( GtkWidget * WXUNUSED(widget), wxGLCanvas *win )
56{
dc3065a5
VZ
57 wxPaintEvent event( win->GetId() );
58 event.SetEventObject( win );
59 win->GetEventHandler()->ProcessEvent( event );
8b089c5e 60
dc3065a5
VZ
61 win->m_exposed = false;
62 win->GetUpdateRegion().Clear();
8b089c5e
JS
63
64 return FALSE;
65}
865bb325 66}
8b089c5e
JS
67
68//-----------------------------------------------------------------------------
69// "expose_event" of m_wxwindow
70//-----------------------------------------------------------------------------
71
865bb325 72extern "C" {
6d727f6c 73static gboolean
8b089c5e
JS
74gtk_glwindow_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxGLCanvas *win )
75{
670f9935 76 win->m_exposed = true;
8b089c5e
JS
77
78 win->GetUpdateRegion().Union( gdk_event->area.x,
79 gdk_event->area.y,
80 gdk_event->area.width,
81 gdk_event->area.height );
6d727f6c 82 return false;
8b089c5e 83}
865bb325 84}
8b089c5e 85
8b089c5e
JS
86//-----------------------------------------------------------------------------
87// "size_allocate" of m_wxwindow
88//-----------------------------------------------------------------------------
89
865bb325 90extern "C" {
2b5f62a0 91static void
8b089c5e
JS
92gtk_glcanvas_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxGLCanvas *win )
93{
8b089c5e
JS
94 if (!win->m_hasVMT)
95 return;
96
97 wxSizeEvent event( wxSize(win->m_width,win->m_height), win->GetId() );
98 event.SetEventObject( win );
99 win->GetEventHandler()->ProcessEvent( event );
100}
865bb325 101}
8b089c5e
JS
102
103//---------------------------------------------------------------------------
104// wxGlCanvas
105//---------------------------------------------------------------------------
106
4660d7e5 107IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
8b089c5e 108
dc3065a5
VZ
109wxGLCanvas::wxGLCanvas(wxWindow *parent,
110 wxWindowID id,
111 const int *attribList,
112 const wxPoint& pos,
113 const wxSize& size,
114 long style,
115 const wxString& name,
116 const wxPalette& palette)
117#if WXWIN_COMPATIBILITY_2_8
b7ea712c 118 : m_createImplicitContext(false)
dc3065a5 119#endif
b7ea712c 120{
dc3065a5 121 Create(parent, id, pos, size, style, name, attribList, palette);
b7ea712c
RR
122}
123
dc3065a5
VZ
124#if WXWIN_COMPATIBILITY_2_8
125
126wxGLCanvas::wxGLCanvas(wxWindow *parent,
127 wxWindowID id,
128 const wxPoint& pos,
129 const wxSize& size,
130 long style,
131 const wxString& name,
132 const int *attribList,
133 const wxPalette& palette)
b7ea712c 134 : m_createImplicitContext(true)
8b089c5e 135{
dc3065a5 136 Create(parent, id, pos, size, style, name, attribList, palette);
8b089c5e
JS
137}
138
dc3065a5
VZ
139wxGLCanvas::wxGLCanvas(wxWindow *parent,
140 const wxGLContext *shared,
141 wxWindowID id,
142 const wxPoint& pos,
143 const wxSize& size,
144 long style,
145 const wxString& name,
146 const int *attribList,
147 const wxPalette& palette)
b7ea712c 148 : m_createImplicitContext(true)
2b5f62a0 149{
dc3065a5
VZ
150 m_sharedContext = wx_const_cast(wxGLContext *, shared);
151
152 Create(parent, id, pos, size, style, name, attribList, palette);
8b089c5e
JS
153}
154
dc3065a5
VZ
155wxGLCanvas::wxGLCanvas(wxWindow *parent,
156 const wxGLCanvas *shared,
157 wxWindowID id,
158 const wxPoint& pos, const wxSize& size,
159 long style, const wxString& name,
160 const int *attribList,
161 const wxPalette& palette )
b7ea712c 162 : m_createImplicitContext(true)
2b5f62a0 163{
dc3065a5
VZ
164 m_sharedContextOf = wx_const_cast(wxGLCanvas *, shared);
165
166 Create(parent, id, pos, size, style, name, attribList, palette);
8b089c5e
JS
167}
168
dc3065a5 169#endif // WXWIN_COMPATIBILITY_2_8
2b5f62a0 170
dc3065a5
VZ
171bool wxGLCanvas::Create(wxWindow *parent,
172 wxWindowID id,
173 const wxPoint& pos,
174 const wxSize& size,
175 long style,
176 const wxString& name,
177 const int *attribList,
178 const wxPalette& palette)
179{
670f9935
WS
180 m_exposed = false;
181 m_noExpose = true;
182 m_nativeSizeEvent = true;
34a34b02 183
498ace9e
VZ
184 if ( !InitVisual(attribList) )
185 return false;
2b5f62a0 186
498ace9e 187 XVisualInfo * const xvi = GetXVisualInfo();
b4d06fb7 188
fee7a683
MR
189 GdkVisual *visual;
190 GdkColormap *colormap;
2b5f62a0 191
fee7a683 192 // MR: This needs a fix for lower gtk+ versions too. Might need to rethink logic (FIXME)
b3f4c570 193#if defined(__WXGTK20__) && GTK_CHECK_VERSION(2,2,0)
fee7a683
MR
194 if (!gtk_check_version(2,2,0))
195 {
196 wxWindow::Create( parent, id, pos, size, style, name );
197
198 m_glWidget = m_wxwindow;
199
200 GdkScreen *screen = gtk_widget_get_screen( m_glWidget );
201 colormap = gdk_screen_get_default_colormap(screen);
202 visual = gdk_colormap_get_visual(colormap);
203
498ace9e 204 if (GDK_VISUAL_XVISUAL(visual)->visualid != xvi->visualid)
fee7a683 205 {
498ace9e 206 visual = gdk_x11_screen_lookup_visual( screen, xvi->visualid );
fee7a683
MR
207 colormap = gdk_colormap_new(visual, FALSE);
208 }
209
210 gtk_widget_set_colormap( m_glWidget, colormap );
211 }
212 else
dc3065a5 213#endif // GTK+ >= 2.2
fee7a683 214 {
498ace9e 215 visual = gdkx_visual_get( xvi->visualid );
fee7a683 216 colormap = gdk_colormap_new( visual, TRUE );
a6f5aa49 217
fee7a683 218 gtk_widget_push_colormap( colormap );
a6f5aa49 219
fee7a683
MR
220 wxWindow::Create( parent, id, pos, size, style, name );
221 m_glWidget = m_wxwindow;
222 }
2b5f62a0 223
2b5b9325 224 gtk_widget_set_double_buffered( m_glWidget, FALSE );
2b5b9325 225
dc3065a5 226#if WXWIN_COMPATIBILITY_2_8
b7ea712c 227 g_signal_connect(m_wxwindow, "realize", G_CALLBACK(gtk_glwindow_realized_callback), this);
dc3065a5 228#endif // WXWIN_COMPATIBILITY_2_8
b7ea712c
RR
229 g_signal_connect(m_wxwindow, "map", G_CALLBACK(gtk_glwindow_map_callback), this);
230 g_signal_connect(m_wxwindow, "expose_event", G_CALLBACK(gtk_glwindow_expose_callback), this);
231 g_signal_connect(m_widget, "size_allocate", G_CALLBACK(gtk_glcanvas_size_callback), this);
a6f5aa49 232
fee7a683
MR
233 if (gtk_check_version(2,2,0) != NULL)
234 {
fee7a683
MR
235 gtk_widget_pop_colormap();
236 }
2b5f62a0 237
dc3065a5 238#if WXWIN_COMPATIBILITY_2_8
bc869971
VZ
239 // if our parent window is already visible, we had been realized before we
240 // connected to the "realize" signal and hence our m_glContext hasn't been
241 // initialized yet and we have to do it now
242 if (GTK_WIDGET_REALIZED(m_wxwindow))
243 gtk_glwindow_realized_callback( m_wxwindow, this );
dc3065a5 244#endif // WXWIN_COMPATIBILITY_2_8
bc869971
VZ
245
246 if (GTK_WIDGET_MAPPED(m_wxwindow))
247 gtk_glwindow_map_callback( m_wxwindow, this );
248
670f9935 249 return true;
a6f5aa49
VZ
250}
251
498ace9e 252Window wxGLCanvas::GetXWindow() const
8b089c5e 253{
b7ea712c 254 GdkWindow *window = GTK_PIZZA(m_wxwindow)->bin_window;
498ace9e 255 return window ? GDK_WINDOW_XWINDOW(window) : 0;
8b089c5e
JS
256}
257
8b089c5e
JS
258void wxGLCanvas::OnInternalIdle()
259{
dc3065a5 260 if (m_exposed)
8b089c5e
JS
261 {
262 wxPaintEvent event( GetId() );
263 event.SetEventObject( this );
264 GetEventHandler()->ProcessEvent( event );
265
670f9935 266 m_exposed = false;
8b089c5e
JS
267 GetUpdateRegion().Clear();
268 }
2b5f62a0 269
8b089c5e
JS
270 wxWindow::OnInternalIdle();
271}
272
dc3065a5
VZ
273#if WXWIN_COMPATIBILITY_2_8
274
275void wxGLCanvas::GTKInitImplicitContext()
276{
277 if ( !m_glContext && m_createImplicitContext )
278 {
279 wxGLContext *share = m_sharedContext;
280 if ( !share && m_sharedContextOf )
281 share = m_sharedContextOf->m_glContext;
282
283 m_glContext = new wxGLContext(this, share);
284 }
285}
a6f5aa49 286
dc3065a5 287#endif // WXWIN_COMPATIBILITY_2_8
a6f5aa49 288
dc3065a5 289#endif // wxUSE_GLCANVAS