]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/gtk/glcanvas.cpp
first attempt at adding the minimal set needed for dead-key support, see #15345
[wxWidgets.git] / src / gtk / glcanvas.cpp
... / ...
CommitLineData
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// Copyright: (c) Robert Roebling
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#if wxUSE_GLCANVAS
15
16#include "wx/glcanvas.h"
17
18#include <gtk/gtk.h>
19#include <gdk/gdkx.h>
20#include "wx/gtk/private/gtk2-compat.h"
21
22#if WXWIN_COMPATIBILITY_2_8
23
24//-----------------------------------------------------------------------------
25// "realize" from m_wxwindow: used to create m_glContext implicitly
26//-----------------------------------------------------------------------------
27
28extern "C" {
29static void
30gtk_glwindow_realized_callback( GtkWidget *WXUNUSED(widget), wxGLCanvas *win )
31{
32 win->GTKInitImplicitContext();
33}
34}
35
36#endif // WXWIN_COMPATIBILITY_2_8
37
38//-----------------------------------------------------------------------------
39// "map" from m_wxwindow
40//-----------------------------------------------------------------------------
41
42#ifndef __WXGTK3__
43extern "C" {
44static void
45gtk_glwindow_map_callback( GtkWidget * WXUNUSED(widget), wxGLCanvas *win )
46{
47 wxPaintEvent event( win->GetId() );
48 event.SetEventObject( win );
49 win->HandleWindowEvent( event );
50
51 win->m_exposed = false;
52 win->GetUpdateRegion().Clear();
53}
54}
55#endif
56
57//-----------------------------------------------------------------------------
58// "expose_event" of m_wxwindow
59//-----------------------------------------------------------------------------
60
61extern "C" {
62#ifdef __WXGTK3__
63static gboolean draw(GtkWidget*, cairo_t* cr, wxGLCanvas* win)
64{
65 win->m_exposed = true;
66 if (win->m_cairoPaintContext == NULL)
67 {
68 win->m_cairoPaintContext = cr;
69 cairo_reference(cr);
70 }
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));
74 return false;
75}
76#else
77static gboolean
78gtk_glwindow_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxGLCanvas *win )
79{
80 win->m_exposed = true;
81
82 win->GetUpdateRegion().Union( gdk_event->area.x,
83 gdk_event->area.y,
84 gdk_event->area.width,
85 gdk_event->area.height );
86 return false;
87}
88#endif
89}
90
91//-----------------------------------------------------------------------------
92// "size_allocate" of m_wxwindow
93//-----------------------------------------------------------------------------
94
95extern "C" {
96static void
97gtk_glcanvas_size_callback(GtkWidget *WXUNUSED(widget),
98 GtkAllocation * WXUNUSED(alloc),
99 wxGLCanvas *win)
100{
101 wxSizeEvent event( wxSize(win->m_width,win->m_height), win->GetId() );
102 event.SetEventObject( win );
103 win->HandleWindowEvent( event );
104}
105}
106
107//-----------------------------------------------------------------------------
108// emission hook for "parent-set"
109//-----------------------------------------------------------------------------
110
111extern "C" {
112static gboolean
113parent_set_hook(GSignalInvocationHint*, guint, const GValue* param_values, void* data)
114{
115 wxGLCanvas* win = (wxGLCanvas*)data;
116 if (g_value_peek_pointer(&param_values[0]) == win->m_wxwindow)
117 {
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)
121 {
122 GdkScreen* screen = gtk_widget_get_screen(win->m_wxwindow);
123 visual = gdk_x11_screen_lookup_visual(screen, xvi->visualid);
124#ifdef __WXGTK3__
125 gtk_widget_set_visual(win->m_wxwindow, visual);
126#else
127 GdkColormap* colormap = gdk_colormap_new(visual, false);
128 gtk_widget_set_colormap(win->m_wxwindow, colormap);
129 g_object_unref(colormap);
130#endif
131 }
132 // remove hook
133 return false;
134 }
135 return true;
136}
137}
138
139//---------------------------------------------------------------------------
140// wxGlCanvas
141//---------------------------------------------------------------------------
142
143IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
144
145wxGLCanvas::wxGLCanvas(wxWindow *parent,
146 wxWindowID id,
147 const int *attribList,
148 const wxPoint& pos,
149 const wxSize& size,
150 long style,
151 const wxString& name,
152 const wxPalette& palette)
153#if WXWIN_COMPATIBILITY_2_8
154 : m_createImplicitContext(false)
155#endif
156{
157 Create(parent, id, pos, size, style, name, attribList, palette);
158}
159
160#if WXWIN_COMPATIBILITY_2_8
161
162wxGLCanvas::wxGLCanvas(wxWindow *parent,
163 wxWindowID id,
164 const wxPoint& pos,
165 const wxSize& size,
166 long style,
167 const wxString& name,
168 const int *attribList,
169 const wxPalette& palette)
170 : m_createImplicitContext(true)
171{
172 m_sharedContext = NULL;
173 m_sharedContextOf = NULL;
174
175 Create(parent, id, pos, size, style, name, attribList, palette);
176}
177
178wxGLCanvas::wxGLCanvas(wxWindow *parent,
179 const wxGLContext *shared,
180 wxWindowID id,
181 const wxPoint& pos,
182 const wxSize& size,
183 long style,
184 const wxString& name,
185 const int *attribList,
186 const wxPalette& palette)
187 : m_createImplicitContext(true)
188{
189 m_sharedContext = const_cast<wxGLContext *>(shared);
190
191 Create(parent, id, pos, size, style, name, attribList, palette);
192}
193
194wxGLCanvas::wxGLCanvas(wxWindow *parent,
195 const wxGLCanvas *shared,
196 wxWindowID id,
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)
202{
203 m_sharedContext = NULL;
204 m_sharedContextOf = const_cast<wxGLCanvas *>(shared);
205
206 Create(parent, id, pos, size, style, name, attribList, palette);
207}
208
209#endif // WXWIN_COMPATIBILITY_2_8
210
211bool wxGLCanvas::Create(wxWindow *parent,
212 wxWindowID id,
213 const wxPoint& pos,
214 const wxSize& size,
215 long style,
216 const wxString& name,
217 const int *attribList,
218 const wxPalette& palette)
219{
220#if wxUSE_PALETTE
221 wxASSERT_MSG( !palette.IsOk(), wxT("palettes not supported") );
222#endif // wxUSE_PALETTE
223 wxUnusedVar(palette); // Unused when wxDEBUG_LEVEL==0
224
225 m_exposed = false;
226 m_noExpose = true;
227 m_nativeSizeEvent = true;
228#ifdef __WXGTK3__
229 m_cairoPaintContext = NULL;
230 m_backgroundStyle = wxBG_STYLE_PAINT;
231#endif
232
233 if ( !InitVisual(attribList) )
234 return false;
235
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);
241
242 wxWindow::Create( parent, id, pos, size, style, name );
243
244 gtk_widget_set_double_buffered(m_wxwindow, false);
245
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
249#ifdef __WXGTK3__
250 g_signal_connect(m_wxwindow, "draw", G_CALLBACK(draw), this);
251#else
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);
254#endif
255 g_signal_connect(m_widget, "size_allocate", G_CALLBACK(gtk_glcanvas_size_callback), this);
256
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
264
265#ifndef __WXGTK3__
266 if (gtk_widget_get_mapped(m_wxwindow))
267 gtk_glwindow_map_callback( m_wxwindow, this );
268#endif
269
270 return true;
271}
272
273bool wxGLCanvas::SetBackgroundStyle(wxBackgroundStyle /* style */)
274{
275 return false;
276}
277
278Window wxGLCanvas::GetXWindow() const
279{
280 GdkWindow* window = GTKGetDrawingWindow();
281 return window ? GDK_WINDOW_XID(window) : 0;
282}
283
284void wxGLCanvas::OnInternalIdle()
285{
286 if (m_exposed)
287 {
288#ifdef __WXGTK3__
289 GTKSendPaintEvents(m_cairoPaintContext);
290 cairo_destroy(m_cairoPaintContext);
291 m_cairoPaintContext = NULL;
292#else
293 wxPaintEvent event( GetId() );
294 event.SetEventObject( this );
295 HandleWindowEvent( event );
296#endif
297
298 m_exposed = false;
299 GetUpdateRegion().Clear();
300 }
301
302 wxWindow::OnInternalIdle();
303}
304
305#if WXWIN_COMPATIBILITY_2_8
306
307void wxGLCanvas::GTKInitImplicitContext()
308{
309 if ( !m_glContext && m_createImplicitContext )
310 {
311 wxGLContext *share = m_sharedContext;
312 if ( !share && m_sharedContextOf )
313 share = m_sharedContextOf->m_glContext;
314
315 m_glContext = new wxGLContext(this, share);
316 }
317}
318
319#endif // WXWIN_COMPATIBILITY_2_8
320
321#endif // wxUSE_GLCANVAS