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