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"
21 #include "wx/gtk/private/gtk2-compat.h"
23 #if WXWIN_COMPATIBILITY_2_8
25 //-----------------------------------------------------------------------------
26 // "realize" from m_wxwindow: used to create m_glContext implicitly
27 //-----------------------------------------------------------------------------
31 gtk_glwindow_realized_callback( GtkWidget
*WXUNUSED(widget
), wxGLCanvas
*win
)
33 win
->GTKInitImplicitContext();
37 #endif // WXWIN_COMPATIBILITY_2_8
39 //-----------------------------------------------------------------------------
40 // "map" from m_wxwindow
41 //-----------------------------------------------------------------------------
46 gtk_glwindow_map_callback( GtkWidget
* WXUNUSED(widget
), wxGLCanvas
*win
)
48 wxPaintEvent
event( win
->GetId() );
49 event
.SetEventObject( win
);
50 win
->HandleWindowEvent( event
);
52 win
->m_exposed
= false;
53 win
->GetUpdateRegion().Clear();
58 //-----------------------------------------------------------------------------
59 // "expose_event" of m_wxwindow
60 //-----------------------------------------------------------------------------
64 static gboolean
draw(GtkWidget
*, cairo_t
* cr
, wxGLCanvas
* win
)
66 win
->m_exposed
= true;
67 if (win
->m_cairoPaintContext
== NULL
)
69 win
->m_cairoPaintContext
= cr
;
72 double x1
, y1
, x2
, y2
;
73 cairo_clip_extents(cr
, &x1
, &y1
, &x2
, &y2
);
74 win
->GetUpdateRegion().Union(int(x1
), int(y1
), int(x2
- x1
), int(y2
- y1
));
79 gtk_glwindow_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxGLCanvas
*win
)
81 win
->m_exposed
= true;
83 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
85 gdk_event
->area
.width
,
86 gdk_event
->area
.height
);
92 //-----------------------------------------------------------------------------
93 // "size_allocate" of m_wxwindow
94 //-----------------------------------------------------------------------------
98 gtk_glcanvas_size_callback(GtkWidget
*WXUNUSED(widget
),
99 GtkAllocation
* WXUNUSED(alloc
),
105 wxSizeEvent
event( wxSize(win
->m_width
,win
->m_height
), win
->GetId() );
106 event
.SetEventObject( win
);
107 win
->HandleWindowEvent( event
);
111 //-----------------------------------------------------------------------------
112 // emission hook for "parent-set"
113 //-----------------------------------------------------------------------------
117 parent_set_hook(GSignalInvocationHint
*, guint
, const GValue
* param_values
, void* data
)
119 wxGLCanvas
* win
= (wxGLCanvas
*)data
;
120 if (g_value_peek_pointer(¶m_values
[0]) == win
->m_wxwindow
)
122 const XVisualInfo
* xvi
= win
->GetXVisualInfo();
123 GdkVisual
* visual
= gtk_widget_get_visual(win
->m_wxwindow
);
124 if (GDK_VISUAL_XVISUAL(visual
)->visualid
!= xvi
->visualid
)
126 GdkScreen
* screen
= gtk_widget_get_screen(win
->m_wxwindow
);
127 visual
= gdk_x11_screen_lookup_visual(screen
, xvi
->visualid
);
129 gtk_widget_set_visual(win
->m_wxwindow
, visual
);
131 GdkColormap
* colormap
= gdk_colormap_new(visual
, false);
132 gtk_widget_set_colormap(win
->m_wxwindow
, colormap
);
133 g_object_unref(colormap
);
143 //---------------------------------------------------------------------------
145 //---------------------------------------------------------------------------
147 IMPLEMENT_CLASS(wxGLCanvas
, wxWindow
)
149 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
151 const int *attribList
,
155 const wxString
& name
,
156 const wxPalette
& palette
)
157 #if WXWIN_COMPATIBILITY_2_8
158 : m_createImplicitContext(false)
161 Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
);
164 #if WXWIN_COMPATIBILITY_2_8
166 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
171 const wxString
& name
,
172 const int *attribList
,
173 const wxPalette
& palette
)
174 : m_createImplicitContext(true)
176 m_sharedContext
= NULL
;
177 m_sharedContextOf
= NULL
;
179 Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
);
182 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
183 const wxGLContext
*shared
,
188 const wxString
& name
,
189 const int *attribList
,
190 const wxPalette
& palette
)
191 : m_createImplicitContext(true)
193 m_sharedContext
= const_cast<wxGLContext
*>(shared
);
195 Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
);
198 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
199 const wxGLCanvas
*shared
,
201 const wxPoint
& pos
, const wxSize
& size
,
202 long style
, const wxString
& name
,
203 const int *attribList
,
204 const wxPalette
& palette
)
205 : m_createImplicitContext(true)
207 m_sharedContext
= NULL
;
208 m_sharedContextOf
= const_cast<wxGLCanvas
*>(shared
);
210 Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
);
213 #endif // WXWIN_COMPATIBILITY_2_8
215 bool wxGLCanvas::Create(wxWindow
*parent
,
220 const wxString
& name
,
221 const int *attribList
,
222 const wxPalette
& palette
)
225 wxASSERT_MSG( !palette
.IsOk(), wxT("palettes not supported") );
226 #endif // wxUSE_PALETTE
227 wxUnusedVar(palette
); // Unused when wxDEBUG_LEVEL==0
231 m_nativeSizeEvent
= true;
233 m_cairoPaintContext
= NULL
;
234 m_backgroundStyle
= wxBG_STYLE_PAINT
;
237 if ( !InitVisual(attribList
) )
240 // watch for the "parent-set" signal on m_wxwindow so we can set colormap
241 // before m_wxwindow is realized (which will occur before
242 // wxWindow::Create() returns if parent is already visible)
243 unsigned sig_id
= g_signal_lookup("parent-set", GTK_TYPE_WIDGET
);
244 g_signal_add_emission_hook(sig_id
, 0, parent_set_hook
, this, NULL
);
246 wxWindow::Create( parent
, id
, pos
, size
, style
, name
);
248 gtk_widget_set_double_buffered(m_wxwindow
, false);
250 #if WXWIN_COMPATIBILITY_2_8
251 g_signal_connect(m_wxwindow
, "realize", G_CALLBACK(gtk_glwindow_realized_callback
), this);
252 #endif // WXWIN_COMPATIBILITY_2_8
254 g_signal_connect(m_wxwindow
, "draw", G_CALLBACK(draw
), this);
256 g_signal_connect(m_wxwindow
, "map", G_CALLBACK(gtk_glwindow_map_callback
), this);
257 g_signal_connect(m_wxwindow
, "expose_event", G_CALLBACK(gtk_glwindow_expose_callback
), this);
259 g_signal_connect(m_widget
, "size_allocate", G_CALLBACK(gtk_glcanvas_size_callback
), this);
261 #if WXWIN_COMPATIBILITY_2_8
262 // if our parent window is already visible, we had been realized before we
263 // connected to the "realize" signal and hence our m_glContext hasn't been
264 // initialized yet and we have to do it now
265 if (gtk_widget_get_realized(m_wxwindow
))
266 gtk_glwindow_realized_callback( m_wxwindow
, this );
267 #endif // WXWIN_COMPATIBILITY_2_8
270 if (gtk_widget_get_mapped(m_wxwindow
))
271 gtk_glwindow_map_callback( m_wxwindow
, this );
277 bool wxGLCanvas::SetBackgroundStyle(wxBackgroundStyle
/* style */)
282 Window
wxGLCanvas::GetXWindow() const
284 GdkWindow
* window
= GTKGetDrawingWindow();
285 return window
? GDK_WINDOW_XID(window
) : 0;
288 void wxGLCanvas::OnInternalIdle()
293 GTKSendPaintEvents(m_cairoPaintContext
);
294 cairo_destroy(m_cairoPaintContext
);
295 m_cairoPaintContext
= NULL
;
297 wxPaintEvent
event( GetId() );
298 event
.SetEventObject( this );
299 HandleWindowEvent( event
);
303 GetUpdateRegion().Clear();
306 wxWindow::OnInternalIdle();
309 #if WXWIN_COMPATIBILITY_2_8
311 void wxGLCanvas::GTKInitImplicitContext()
313 if ( !m_glContext
&& m_createImplicitContext
)
315 wxGLContext
*share
= m_sharedContext
;
316 if ( !share
&& m_sharedContextOf
)
317 share
= m_sharedContextOf
->m_glContext
;
319 m_glContext
= new wxGLContext(this, share
);
323 #endif // WXWIN_COMPATIBILITY_2_8
325 #endif // wxUSE_GLCANVAS