1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/glcanvas.cpp
3 // Purpose: wxGLCanvas, for using OpenGL/Mesa with wxWidgets and GTK
4 // Author: Robert Roebling
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
17 #include "wx/glcanvas.h"
22 #if WXWIN_COMPATIBILITY_2_8
24 //-----------------------------------------------------------------------------
25 // "realize" from m_wxwindow: used to create m_glContext implicitly
26 //-----------------------------------------------------------------------------
30 gtk_glwindow_realized_callback( GtkWidget
*WXUNUSED(widget
), wxGLCanvas
*win
)
32 win
->GTKInitImplicitContext();
36 #endif // WXWIN_COMPATIBILITY_2_8
38 //-----------------------------------------------------------------------------
39 // "map" from m_wxwindow
40 //-----------------------------------------------------------------------------
44 gtk_glwindow_map_callback( GtkWidget
* WXUNUSED(widget
), wxGLCanvas
*win
)
46 wxPaintEvent
event( win
->GetId() );
47 event
.SetEventObject( win
);
48 win
->HandleWindowEvent( event
);
50 win
->m_exposed
= false;
51 win
->GetUpdateRegion().Clear();
55 //-----------------------------------------------------------------------------
56 // "expose_event" of m_wxwindow
57 //-----------------------------------------------------------------------------
61 gtk_glwindow_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxGLCanvas
*win
)
63 win
->m_exposed
= true;
65 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
67 gdk_event
->area
.width
,
68 gdk_event
->area
.height
);
73 //-----------------------------------------------------------------------------
74 // "size_allocate" of m_wxwindow
75 //-----------------------------------------------------------------------------
79 gtk_glcanvas_size_callback(GtkWidget
*WXUNUSED(widget
),
80 GtkAllocation
* WXUNUSED(alloc
),
86 wxSizeEvent
event( wxSize(win
->m_width
,win
->m_height
), win
->GetId() );
87 event
.SetEventObject( win
);
88 win
->HandleWindowEvent( event
);
92 //-----------------------------------------------------------------------------
93 // emission hook for "parent-set"
94 //-----------------------------------------------------------------------------
98 parent_set_hook(GSignalInvocationHint
*, guint
, const GValue
* param_values
, void* data
)
100 wxGLCanvas
* win
= (wxGLCanvas
*)data
;
101 if (g_value_peek_pointer(¶m_values
[0]) == win
->m_wxwindow
)
103 const XVisualInfo
* xvi
= win
->GetXVisualInfo();
104 GdkVisual
* visual
= gtk_widget_get_visual(win
->m_wxwindow
);
105 if (GDK_VISUAL_XVISUAL(visual
)->visualid
!= xvi
->visualid
)
107 GdkScreen
* screen
= gtk_widget_get_screen(win
->m_wxwindow
);
108 visual
= gdk_x11_screen_lookup_visual(screen
, xvi
->visualid
);
109 GdkColormap
* colormap
= gdk_colormap_new(visual
, false);
110 gtk_widget_set_colormap(win
->m_wxwindow
, colormap
);
111 g_object_unref(colormap
);
120 //---------------------------------------------------------------------------
122 //---------------------------------------------------------------------------
124 IMPLEMENT_CLASS(wxGLCanvas
, wxWindow
)
126 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
128 const int *attribList
,
132 const wxString
& name
,
133 const wxPalette
& palette
)
134 #if WXWIN_COMPATIBILITY_2_8
135 : m_createImplicitContext(false)
138 Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
);
141 #if WXWIN_COMPATIBILITY_2_8
143 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
148 const wxString
& name
,
149 const int *attribList
,
150 const wxPalette
& palette
)
151 : m_createImplicitContext(true)
153 m_sharedContext
= NULL
;
154 m_sharedContextOf
= NULL
;
156 Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
);
159 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
160 const wxGLContext
*shared
,
165 const wxString
& name
,
166 const int *attribList
,
167 const wxPalette
& palette
)
168 : m_createImplicitContext(true)
170 m_sharedContext
= const_cast<wxGLContext
*>(shared
);
172 Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
);
175 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
176 const wxGLCanvas
*shared
,
178 const wxPoint
& pos
, const wxSize
& size
,
179 long style
, const wxString
& name
,
180 const int *attribList
,
181 const wxPalette
& palette
)
182 : m_createImplicitContext(true)
184 m_sharedContext
= NULL
;
185 m_sharedContextOf
= const_cast<wxGLCanvas
*>(shared
);
187 Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
);
190 #endif // WXWIN_COMPATIBILITY_2_8
192 bool wxGLCanvas::Create(wxWindow
*parent
,
197 const wxString
& name
,
198 const int *attribList
,
199 const wxPalette
& palette
)
202 wxASSERT_MSG( !palette
.IsOk(), wxT("palettes not supported") );
203 #endif // wxUSE_PALETTE
204 wxUnusedVar(palette
); // Unused when wxDEBUG_LEVEL==0
208 m_nativeSizeEvent
= true;
210 if ( !InitVisual(attribList
) )
213 // watch for the "parent-set" signal on m_wxwindow so we can set colormap
214 // before m_wxwindow is realized (which will occur before
215 // wxWindow::Create() returns if parent is already visible)
216 unsigned sig_id
= g_signal_lookup("parent-set", GTK_TYPE_WIDGET
);
217 g_signal_add_emission_hook(sig_id
, 0, parent_set_hook
, this, NULL
);
219 wxWindow::Create( parent
, id
, pos
, size
, style
, name
);
221 gtk_widget_set_double_buffered(m_wxwindow
, false);
223 #if WXWIN_COMPATIBILITY_2_8
224 g_signal_connect(m_wxwindow
, "realize", G_CALLBACK(gtk_glwindow_realized_callback
), this);
225 #endif // WXWIN_COMPATIBILITY_2_8
226 g_signal_connect(m_wxwindow
, "map", G_CALLBACK(gtk_glwindow_map_callback
), this);
227 g_signal_connect(m_wxwindow
, "expose_event", G_CALLBACK(gtk_glwindow_expose_callback
), this);
228 g_signal_connect(m_widget
, "size_allocate", G_CALLBACK(gtk_glcanvas_size_callback
), this);
230 #if WXWIN_COMPATIBILITY_2_8
231 // if our parent window is already visible, we had been realized before we
232 // connected to the "realize" signal and hence our m_glContext hasn't been
233 // initialized yet and we have to do it now
234 if (GTK_WIDGET_REALIZED(m_wxwindow
))
235 gtk_glwindow_realized_callback( m_wxwindow
, this );
236 #endif // WXWIN_COMPATIBILITY_2_8
238 if (GTK_WIDGET_MAPPED(m_wxwindow
))
239 gtk_glwindow_map_callback( m_wxwindow
, this );
244 Window
wxGLCanvas::GetXWindow() const
246 GdkWindow
* window
= GTKGetDrawingWindow();
247 return window
? GDK_WINDOW_XWINDOW(window
) : 0;
250 void wxGLCanvas::OnInternalIdle()
254 wxPaintEvent
event( GetId() );
255 event
.SetEventObject( this );
256 HandleWindowEvent( event
);
259 GetUpdateRegion().Clear();
262 wxWindow::OnInternalIdle();
265 #if WXWIN_COMPATIBILITY_2_8
267 void wxGLCanvas::GTKInitImplicitContext()
269 if ( !m_glContext
&& m_createImplicitContext
)
271 wxGLContext
*share
= m_sharedContext
;
272 if ( !share
&& m_sharedContextOf
)
273 share
= m_sharedContextOf
->m_glContext
;
275 m_glContext
= new wxGLContext(this, share
);
279 #endif // WXWIN_COMPATIBILITY_2_8
281 #endif // wxUSE_GLCANVAS