]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/glcanvas.cpp
Add wxEvtHandler::CallAfter() for asynchronous method calls.
[wxWidgets.git] / src / gtk1 / glcanvas.cpp
CommitLineData
8b089c5e 1/////////////////////////////////////////////////////////////////////////////
9b5f1895 2// Name: src/gtk1/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
2b5f62a0
VZ
26extern "C"
27{
8b089c5e
JS
28#include "gtk/gtk.h"
29#include "gdk/gdk.h"
30#include "gdk/gdkx.h"
31}
32
3cbab641 33#include "wx/gtk1/win_gtk.h"
dc3065a5 34#include "wx/gtk1/private.h"
34a34b02 35
8b089c5e
JS
36//-----------------------------------------------------------------------------
37// idle system
38//-----------------------------------------------------------------------------
39
40extern void wxapp_install_idle_handler();
41extern bool g_isIdle;
42
dc3065a5 43#if WXWIN_COMPATIBILITY_2_8
8b089c5e
JS
44
45//-----------------------------------------------------------------------------
dc3065a5 46// "realize" from m_wxwindow: used to create m_glContext implicitly
8b089c5e
JS
47//-----------------------------------------------------------------------------
48
865bb325 49extern "C" {
8b089c5e 50static gint
34a34b02 51gtk_glwindow_realized_callback( GtkWidget *WXUNUSED(widget), wxGLCanvas *win )
8b089c5e 52{
dc3065a5 53 win->GTKInitImplicitContext();
8b089c5e
JS
54
55 return FALSE;
56}
865bb325 57}
8b089c5e 58
dc3065a5
VZ
59#endif // WXWIN_COMPATIBILITY_2_8
60
8b089c5e
JS
61//-----------------------------------------------------------------------------
62// "map" from m_wxwindow
63//-----------------------------------------------------------------------------
64
865bb325 65extern "C" {
8b089c5e
JS
66static gint
67gtk_glwindow_map_callback( GtkWidget * WXUNUSED(widget), wxGLCanvas *win )
68{
dc3065a5
VZ
69 wxPaintEvent event( win->GetId() );
70 event.SetEventObject( win );
937013e0 71 win->HandleWindowEvent( event );
8b089c5e 72
dc3065a5 73 win->GetUpdateRegion().Clear();
8b089c5e
JS
74
75 return FALSE;
76}
865bb325 77}
8b089c5e
JS
78
79//-----------------------------------------------------------------------------
80// "expose_event" of m_wxwindow
81//-----------------------------------------------------------------------------
82
865bb325 83extern "C" {
2b5f62a0 84static void
8b089c5e
JS
85gtk_glwindow_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxGLCanvas *win )
86{
2b5f62a0 87 if (g_isIdle)
8b089c5e
JS
88 wxapp_install_idle_handler();
89
8b089c5e
JS
90 win->GetUpdateRegion().Union( gdk_event->area.x,
91 gdk_event->area.y,
92 gdk_event->area.width,
93 gdk_event->area.height );
94}
865bb325 95}
8b089c5e
JS
96
97//-----------------------------------------------------------------------------
98// "draw" of m_wxwindow
99//-----------------------------------------------------------------------------
100
865bb325 101extern "C" {
2b5f62a0 102static void
8b089c5e
JS
103gtk_glwindow_draw_callback( GtkWidget *WXUNUSED(widget), GdkRectangle *rect, wxGLCanvas *win )
104{
2b5f62a0 105 if (g_isIdle)
8b089c5e
JS
106 wxapp_install_idle_handler();
107
8b089c5e
JS
108 win->GetUpdateRegion().Union( rect->x, rect->y,
109 rect->width, rect->height );
110}
865bb325 111}
8b089c5e
JS
112
113//-----------------------------------------------------------------------------
114// "size_allocate" of m_wxwindow
115//-----------------------------------------------------------------------------
116
865bb325 117extern "C" {
2b5f62a0 118static void
8b089c5e
JS
119gtk_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 );
937013e0 129 win->HandleWindowEvent( event );
8b089c5e 130}
865bb325 131}
8b089c5e
JS
132
133//---------------------------------------------------------------------------
134// wxGlCanvas
135//---------------------------------------------------------------------------
136
4660d7e5 137IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
8b089c5e 138
dc3065a5
VZ
139wxGLCanvas::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
8b089c5e 150{
dc3065a5 151 Create(parent, id, pos, size, style, name, attribList, palette);
8b089c5e
JS
152}
153
dc3065a5
VZ
154#if WXWIN_COMPATIBILITY_2_8
155
156wxGLCanvas::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)
2b5f62a0 165{
dc3065a5 166 Create(parent, id, pos, size, style, name, attribList, palette);
8b089c5e
JS
167}
168
dc3065a5
VZ
169wxGLCanvas::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)
2b5f62a0 179{
5c33522f 180 m_sharedContext = const_cast<wxGLContext *>(shared);
dc3065a5
VZ
181
182 Create(parent, id, pos, size, style, name, attribList, palette);
8b089c5e
JS
183}
184
dc3065a5
VZ
185wxGLCanvas::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)
8b089c5e 193{
5c33522f 194 m_sharedContextOf = const_cast<wxGLCanvas *>(shared);
dc3065a5
VZ
195
196 Create(parent, id, pos, size, style, name, attribList, palette);
197}
2b5f62a0 198
dc3065a5
VZ
199#endif // WXWIN_COMPATIBILITY_2_8
200
201bool 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{
670f9935
WS
210 m_noExpose = true;
211 m_nativeSizeEvent = true;
b4d06fb7 212
498ace9e
VZ
213 if ( !InitVisual(attribList) )
214 return false;
2b5f62a0 215
498ace9e
VZ
216 GdkVisual *visual = gdkx_visual_get( GetXVisualInfo()->visualid );
217 GdkColormap *colormap = gdk_colormap_new( visual, TRUE );
fee7a683 218
dc3065a5
VZ
219 gtk_widget_push_colormap( colormap );
220 gtk_widget_push_visual( visual );
fee7a683 221
dc3065a5
VZ
222 wxWindow::Create( parent, id, pos, size, style, name );
223 m_glWidget = m_wxwindow;
2b5f62a0 224
a6f5aa49 225 gtk_pizza_set_clear( GTK_PIZZA(m_wxwindow), FALSE );
2b5f62a0 226
dc3065a5 227#if WXWIN_COMPATIBILITY_2_8
a6f5aa49 228 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
dc3065a5
VZ
229 GTK_SIGNAL_FUNC(gtk_glwindow_realized_callback), (gpointer) this);
230#endif // WXWIN_COMPATIBILITY_2_8
a6f5aa49
VZ
231
232 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "map",
dc3065a5 233 GTK_SIGNAL_FUNC(gtk_glwindow_map_callback), (gpointer) this);
a6f5aa49
VZ
234
235 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
dc3065a5 236 GTK_SIGNAL_FUNC(gtk_glwindow_expose_callback), (gpointer) this);
a6f5aa49
VZ
237
238 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
dc3065a5 239 GTK_SIGNAL_FUNC(gtk_glwindow_draw_callback), (gpointer) this);
2b5f62a0 240
a6f5aa49 241 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
dc3065a5 242 GTK_SIGNAL_FUNC(gtk_glcanvas_size_callback), (gpointer) this);
a6f5aa49 243
3cbab641 244 gtk_widget_pop_visual();
dc3065a5 245
3cbab641 246 gtk_widget_pop_colormap();
2b5f62a0 247
dc3065a5 248#if WXWIN_COMPATIBILITY_2_8
bc869971
VZ
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 );
dc3065a5 254#endif // WXWIN_COMPATIBILITY_2_8
bc869971
VZ
255
256 if (GTK_WIDGET_MAPPED(m_wxwindow))
257 gtk_glwindow_map_callback( m_wxwindow, this );
258
670f9935 259 return true;
a6f5aa49
VZ
260}
261
498ace9e 262Window wxGLCanvas::GetXWindow() const
8b089c5e 263{
dc3065a5 264 GdkWindow *window = GTK_PIZZA(m_wxwindow)->bin_window;
498ace9e 265 return window ? GDK_WINDOW_XWINDOW(window) : 0;
8b089c5e
JS
266}
267
268void wxGLCanvas::OnInternalIdle()
269{
dc3065a5 270 if (!m_updateRegion.IsEmpty())
8b089c5e
JS
271 {
272 wxPaintEvent event( GetId() );
273 event.SetEventObject( this );
937013e0 274 HandleWindowEvent( event );
8b089c5e 275
8b089c5e
JS
276 GetUpdateRegion().Clear();
277 }
2b5f62a0 278
8b089c5e
JS
279 wxWindow::OnInternalIdle();
280}
281
dc3065a5 282#if WXWIN_COMPATIBILITY_2_8
a6f5aa49 283
dc3065a5
VZ
284void 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
a6f5aa49 297
dc3065a5 298#endif // wxUSE_GLCANVAS