Reorganize idle system code.
[wxWidgets.git] / src / gtk / glcanvas.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/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 #include <gtk/gtk.h>
27 #include <gdk/gdkx.h>
28
29 #include "wx/gtk/win_gtk.h"
30
31 #if WXWIN_COMPATIBILITY_2_8
32
33 //-----------------------------------------------------------------------------
34 // "realize" from m_wxwindow: used to create m_glContext implicitly
35 //-----------------------------------------------------------------------------
36
37 extern "C" {
38 static gint
39 gtk_glwindow_realized_callback( GtkWidget *WXUNUSED(widget), wxGLCanvas *win )
40 {
41 win->GTKInitImplicitContext();
42
43 return FALSE;
44 }
45 }
46
47 #endif // WXWIN_COMPATIBILITY_2_8
48
49 //-----------------------------------------------------------------------------
50 // "map" from m_wxwindow
51 //-----------------------------------------------------------------------------
52
53 extern "C" {
54 static gint
55 gtk_glwindow_map_callback( GtkWidget * WXUNUSED(widget), wxGLCanvas *win )
56 {
57 wxPaintEvent event( win->GetId() );
58 event.SetEventObject( win );
59 win->GetEventHandler()->ProcessEvent( event );
60
61 win->m_exposed = false;
62 win->GetUpdateRegion().Clear();
63
64 return FALSE;
65 }
66 }
67
68 //-----------------------------------------------------------------------------
69 // "expose_event" of m_wxwindow
70 //-----------------------------------------------------------------------------
71
72 extern "C" {
73 static gboolean
74 gtk_glwindow_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxGLCanvas *win )
75 {
76 win->m_exposed = true;
77
78 win->GetUpdateRegion().Union( gdk_event->area.x,
79 gdk_event->area.y,
80 gdk_event->area.width,
81 gdk_event->area.height );
82 return false;
83 }
84 }
85
86 //-----------------------------------------------------------------------------
87 // "size_allocate" of m_wxwindow
88 //-----------------------------------------------------------------------------
89
90 extern "C" {
91 static void
92 gtk_glcanvas_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxGLCanvas *win )
93 {
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 }
101 }
102
103 //---------------------------------------------------------------------------
104 // wxGlCanvas
105 //---------------------------------------------------------------------------
106
107 IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
108
109 wxGLCanvas::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
118 : m_createImplicitContext(false)
119 #endif
120 {
121 Create(parent, id, pos, size, style, name, attribList, palette);
122 }
123
124 #if WXWIN_COMPATIBILITY_2_8
125
126 wxGLCanvas::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)
134 : m_createImplicitContext(true)
135 {
136 Create(parent, id, pos, size, style, name, attribList, palette);
137 }
138
139 wxGLCanvas::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)
148 : m_createImplicitContext(true)
149 {
150 m_sharedContext = wx_const_cast(wxGLContext *, shared);
151
152 Create(parent, id, pos, size, style, name, attribList, palette);
153 }
154
155 wxGLCanvas::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 )
162 : m_createImplicitContext(true)
163 {
164 m_sharedContextOf = wx_const_cast(wxGLCanvas *, shared);
165
166 Create(parent, id, pos, size, style, name, attribList, palette);
167 }
168
169 #endif // WXWIN_COMPATIBILITY_2_8
170
171 bool 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 {
180 m_exposed = false;
181 m_noExpose = true;
182 m_nativeSizeEvent = true;
183
184 if ( !InitVisual(attribList) )
185 return false;
186
187 XVisualInfo * const xvi = GetXVisualInfo();
188
189 GdkVisual *visual;
190 GdkColormap *colormap;
191
192 // MR: This needs a fix for lower gtk+ versions too. Might need to rethink logic (FIXME)
193 #if defined(__WXGTK20__) && GTK_CHECK_VERSION(2,2,0)
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
204 if (GDK_VISUAL_XVISUAL(visual)->visualid != xvi->visualid)
205 {
206 visual = gdk_x11_screen_lookup_visual( screen, xvi->visualid );
207 colormap = gdk_colormap_new(visual, FALSE);
208 }
209
210 gtk_widget_set_colormap( m_glWidget, colormap );
211 }
212 else
213 #endif // GTK+ >= 2.2
214 {
215 visual = gdkx_visual_get( xvi->visualid );
216 colormap = gdk_colormap_new( visual, TRUE );
217
218 gtk_widget_push_colormap( colormap );
219
220 wxWindow::Create( parent, id, pos, size, style, name );
221 m_glWidget = m_wxwindow;
222 }
223
224 gtk_widget_set_double_buffered( m_glWidget, FALSE );
225
226 #if WXWIN_COMPATIBILITY_2_8
227 g_signal_connect(m_wxwindow, "realize", G_CALLBACK(gtk_glwindow_realized_callback), this);
228 #endif // WXWIN_COMPATIBILITY_2_8
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);
232
233 if (gtk_check_version(2,2,0) != NULL)
234 {
235 gtk_widget_pop_colormap();
236 }
237
238 #if WXWIN_COMPATIBILITY_2_8
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 );
244 #endif // WXWIN_COMPATIBILITY_2_8
245
246 if (GTK_WIDGET_MAPPED(m_wxwindow))
247 gtk_glwindow_map_callback( m_wxwindow, this );
248
249 return true;
250 }
251
252 Window wxGLCanvas::GetXWindow() const
253 {
254 GdkWindow *window = GTK_PIZZA(m_wxwindow)->bin_window;
255 return window ? GDK_WINDOW_XWINDOW(window) : 0;
256 }
257
258 void wxGLCanvas::OnInternalIdle()
259 {
260 if (m_exposed)
261 {
262 wxPaintEvent event( GetId() );
263 event.SetEventObject( this );
264 GetEventHandler()->ProcessEvent( event );
265
266 m_exposed = false;
267 GetUpdateRegion().Clear();
268 }
269
270 wxWindow::OnInternalIdle();
271 }
272
273 #if WXWIN_COMPATIBILITY_2_8
274
275 void 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 }
286
287 #endif // WXWIN_COMPATIBILITY_2_8
288
289 #endif // wxUSE_GLCANVAS