1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/glcanvas.cpp
3 // Purpose: wxGLCanvas, for using OpenGL/Mesa with wxWidgets and GTK
4 // Author: Robert Roebling
7 // Copyright: (c) Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
16 #include "wx/glcanvas.h"
20 #include "wx/gtk/private/gtk2-compat.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 //-----------------------------------------------------------------------------
45 gtk_glwindow_map_callback( GtkWidget
* WXUNUSED(widget
), wxGLCanvas
*win
)
47 wxPaintEvent
event( win
->GetId() );
48 event
.SetEventObject( win
);
49 win
->HandleWindowEvent( event
);
51 win
->m_exposed
= false;
52 win
->GetUpdateRegion().Clear();
57 //-----------------------------------------------------------------------------
58 // "expose_event" of m_wxwindow
59 //-----------------------------------------------------------------------------
63 static gboolean
draw(GtkWidget
*, cairo_t
* cr
, wxGLCanvas
* win
)
65 win
->m_exposed
= true;
66 if (win
->m_cairoPaintContext
== NULL
)
68 win
->m_cairoPaintContext
= cr
;
71 double x1
, y1
, x2
, y2
;
72 cairo_clip_extents(cr
, &x1
, &y1
, &x2
, &y2
);
73 win
->GetUpdateRegion().Union(int(x1
), int(y1
), int(x2
- x1
), int(y2
- y1
));
78 gtk_glwindow_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxGLCanvas
*win
)
80 win
->m_exposed
= true;
82 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
84 gdk_event
->area
.width
,
85 gdk_event
->area
.height
);
91 //-----------------------------------------------------------------------------
92 // "size_allocate" of m_wxwindow
93 //-----------------------------------------------------------------------------
97 gtk_glcanvas_size_callback(GtkWidget
*WXUNUSED(widget
),
98 GtkAllocation
* WXUNUSED(alloc
),
101 wxSizeEvent
event( wxSize(win
->m_width
,win
->m_height
), win
->GetId() );
102 event
.SetEventObject( win
);
103 win
->HandleWindowEvent( event
);
107 //-----------------------------------------------------------------------------
108 // emission hook for "parent-set"
109 //-----------------------------------------------------------------------------
113 parent_set_hook(GSignalInvocationHint
*, guint
, const GValue
* param_values
, void* data
)
115 wxGLCanvas
* win
= (wxGLCanvas
*)data
;
116 if (g_value_peek_pointer(¶m_values
[0]) == win
->m_wxwindow
)
118 const XVisualInfo
* xvi
= win
->GetXVisualInfo();
119 GdkVisual
* visual
= gtk_widget_get_visual(win
->m_wxwindow
);
120 if (GDK_VISUAL_XVISUAL(visual
)->visualid
!= xvi
->visualid
)
122 GdkScreen
* screen
= gtk_widget_get_screen(win
->m_wxwindow
);
123 visual
= gdk_x11_screen_lookup_visual(screen
, xvi
->visualid
);
125 gtk_widget_set_visual(win
->m_wxwindow
, visual
);
127 GdkColormap
* colormap
= gdk_colormap_new(visual
, false);
128 gtk_widget_set_colormap(win
->m_wxwindow
, colormap
);
129 g_object_unref(colormap
);
139 //---------------------------------------------------------------------------
141 //---------------------------------------------------------------------------
143 IMPLEMENT_CLASS(wxGLCanvas
, wxWindow
)
145 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
147 const int *attribList
,
151 const wxString
& name
,
152 const wxPalette
& palette
)
153 #if WXWIN_COMPATIBILITY_2_8
154 : m_createImplicitContext(false)
157 Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
);
160 #if WXWIN_COMPATIBILITY_2_8
162 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
167 const wxString
& name
,
168 const int *attribList
,
169 const wxPalette
& palette
)
170 : m_createImplicitContext(true)
172 m_sharedContext
= NULL
;
173 m_sharedContextOf
= NULL
;
175 Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
);
178 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
179 const wxGLContext
*shared
,
184 const wxString
& name
,
185 const int *attribList
,
186 const wxPalette
& palette
)
187 : m_createImplicitContext(true)
189 m_sharedContext
= const_cast<wxGLContext
*>(shared
);
191 Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
);
194 wxGLCanvas::wxGLCanvas(wxWindow
*parent
,
195 const wxGLCanvas
*shared
,
197 const wxPoint
& pos
, const wxSize
& size
,
198 long style
, const wxString
& name
,
199 const int *attribList
,
200 const wxPalette
& palette
)
201 : m_createImplicitContext(true)
203 m_sharedContext
= NULL
;
204 m_sharedContextOf
= const_cast<wxGLCanvas
*>(shared
);
206 Create(parent
, id
, pos
, size
, style
, name
, attribList
, palette
);
209 #endif // WXWIN_COMPATIBILITY_2_8
211 bool wxGLCanvas::Create(wxWindow
*parent
,
216 const wxString
& name
,
217 const int *attribList
,
218 const wxPalette
& palette
)
221 wxASSERT_MSG( !palette
.IsOk(), wxT("palettes not supported") );
222 #endif // wxUSE_PALETTE
223 wxUnusedVar(palette
); // Unused when wxDEBUG_LEVEL==0
227 m_nativeSizeEvent
= true;
229 m_cairoPaintContext
= NULL
;
230 m_backgroundStyle
= wxBG_STYLE_PAINT
;
233 if ( !InitVisual(attribList
) )
236 // watch for the "parent-set" signal on m_wxwindow so we can set colormap
237 // before m_wxwindow is realized (which will occur before
238 // wxWindow::Create() returns if parent is already visible)
239 unsigned sig_id
= g_signal_lookup("parent-set", GTK_TYPE_WIDGET
);
240 g_signal_add_emission_hook(sig_id
, 0, parent_set_hook
, this, NULL
);
242 wxWindow::Create( parent
, id
, pos
, size
, style
, name
);
244 gtk_widget_set_double_buffered(m_wxwindow
, false);
246 #if WXWIN_COMPATIBILITY_2_8
247 g_signal_connect(m_wxwindow
, "realize", G_CALLBACK(gtk_glwindow_realized_callback
), this);
248 #endif // WXWIN_COMPATIBILITY_2_8
250 g_signal_connect(m_wxwindow
, "draw", G_CALLBACK(draw
), this);
252 g_signal_connect(m_wxwindow
, "map", G_CALLBACK(gtk_glwindow_map_callback
), this);
253 g_signal_connect(m_wxwindow
, "expose_event", G_CALLBACK(gtk_glwindow_expose_callback
), this);
255 g_signal_connect(m_widget
, "size_allocate", G_CALLBACK(gtk_glcanvas_size_callback
), this);
257 #if WXWIN_COMPATIBILITY_2_8
258 // if our parent window is already visible, we had been realized before we
259 // connected to the "realize" signal and hence our m_glContext hasn't been
260 // initialized yet and we have to do it now
261 if (gtk_widget_get_realized(m_wxwindow
))
262 gtk_glwindow_realized_callback( m_wxwindow
, this );
263 #endif // WXWIN_COMPATIBILITY_2_8
266 if (gtk_widget_get_mapped(m_wxwindow
))
267 gtk_glwindow_map_callback( m_wxwindow
, this );
273 bool wxGLCanvas::SetBackgroundStyle(wxBackgroundStyle
/* style */)
278 Window
wxGLCanvas::GetXWindow() const
280 GdkWindow
* window
= GTKGetDrawingWindow();
281 return window
? GDK_WINDOW_XID(window
) : 0;
284 void wxGLCanvas::OnInternalIdle()
289 GTKSendPaintEvents(m_cairoPaintContext
);
290 cairo_destroy(m_cairoPaintContext
);
291 m_cairoPaintContext
= NULL
;
293 wxPaintEvent
event( GetId() );
294 event
.SetEventObject( this );
295 HandleWindowEvent( event
);
299 GetUpdateRegion().Clear();
302 wxWindow::OnInternalIdle();
305 #if WXWIN_COMPATIBILITY_2_8
307 void wxGLCanvas::GTKInitImplicitContext()
309 if ( !m_glContext
&& m_createImplicitContext
)
311 wxGLContext
*share
= m_sharedContext
;
312 if ( !share
&& m_sharedContextOf
)
313 share
= m_sharedContextOf
->m_glContext
;
315 m_glContext
= new wxGLContext(this, share
);
319 #endif // WXWIN_COMPATIBILITY_2_8
321 #endif // wxUSE_GLCANVAS