]> git.saurik.com Git - wxWidgets.git/blame - 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
8b089c5e 1/////////////////////////////////////////////////////////////////////////////
9b5f1895 2// Name: src/gtk/glcanvas.cpp
77ffb593 3// Purpose: wxGLCanvas, for using OpenGL/Mesa with wxWidgets and GTK
8b089c5e
JS
4// Author: Robert Roebling
5// Modified by:
6// Created: 17/08/98
8b089c5e 7// Copyright: (c) Robert Roebling
65571936 8// Licence: wxWindows licence
8b089c5e
JS
9/////////////////////////////////////////////////////////////////////////////
10
14f355c2
VS
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
8b089c5e
JS
14#if wxUSE_GLCANVAS
15
16#include "wx/glcanvas.h"
17
a1abca32
PC
18#include <gtk/gtk.h>
19#include <gdk/gdkx.h>
86b8b3ac 20#include "wx/gtk/private/gtk2-compat.h"
8b089c5e 21
dc3065a5
VZ
22#if WXWIN_COMPATIBILITY_2_8
23
8b089c5e 24//-----------------------------------------------------------------------------
dc3065a5 25// "realize" from m_wxwindow: used to create m_glContext implicitly
8b089c5e
JS
26//-----------------------------------------------------------------------------
27
865bb325 28extern "C" {
144ae5bb 29static void
34a34b02 30gtk_glwindow_realized_callback( GtkWidget *WXUNUSED(widget), wxGLCanvas *win )
8b089c5e 31{
dc3065a5 32 win->GTKInitImplicitContext();
8b089c5e 33}
865bb325 34}
8b089c5e 35
dc3065a5
VZ
36#endif // WXWIN_COMPATIBILITY_2_8
37
8b089c5e
JS
38//-----------------------------------------------------------------------------
39// "map" from m_wxwindow
40//-----------------------------------------------------------------------------
41
9dc44eff 42#ifndef __WXGTK3__
865bb325 43extern "C" {
144ae5bb 44static void
8b089c5e
JS
45gtk_glwindow_map_callback( GtkWidget * WXUNUSED(widget), wxGLCanvas *win )
46{
dc3065a5
VZ
47 wxPaintEvent event( win->GetId() );
48 event.SetEventObject( win );
937013e0 49 win->HandleWindowEvent( event );
8b089c5e 50
dc3065a5
VZ
51 win->m_exposed = false;
52 win->GetUpdateRegion().Clear();
8b089c5e 53}
865bb325 54}
9dc44eff 55#endif
8b089c5e
JS
56
57//-----------------------------------------------------------------------------
58// "expose_event" of m_wxwindow
59//-----------------------------------------------------------------------------
60
865bb325 61extern "C" {
9dc44eff
PC
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
6d727f6c 77static gboolean
8b089c5e
JS
78gtk_glwindow_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxGLCanvas *win )
79{
670f9935 80 win->m_exposed = true;
8b089c5e
JS
81
82 win->GetUpdateRegion().Union( gdk_event->area.x,
83 gdk_event->area.y,
84 gdk_event->area.width,
85 gdk_event->area.height );
6d727f6c 86 return false;
8b089c5e 87}
9dc44eff 88#endif
865bb325 89}
8b089c5e 90
8b089c5e
JS
91//-----------------------------------------------------------------------------
92// "size_allocate" of m_wxwindow
93//-----------------------------------------------------------------------------
94
865bb325 95extern "C" {
2b5f62a0 96static void
e0d1fd7f
VZ
97gtk_glcanvas_size_callback(GtkWidget *WXUNUSED(widget),
98 GtkAllocation * WXUNUSED(alloc),
99 wxGLCanvas *win)
8b089c5e 100{
8b089c5e
JS
101 wxSizeEvent event( wxSize(win->m_width,win->m_height), win->GetId() );
102 event.SetEventObject( win );
937013e0 103 win->HandleWindowEvent( event );
8b089c5e 104}
865bb325 105}
8b089c5e 106
3780e252
PC
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);
9dc44eff
PC
124#ifdef __WXGTK3__
125 gtk_widget_set_visual(win->m_wxwindow, visual);
126#else
3780e252
PC
127 GdkColormap* colormap = gdk_colormap_new(visual, false);
128 gtk_widget_set_colormap(win->m_wxwindow, colormap);
129 g_object_unref(colormap);
9dc44eff 130#endif
3780e252
PC
131 }
132 // remove hook
133 return false;
134 }
135 return true;
136}
137}
138
8b089c5e
JS
139//---------------------------------------------------------------------------
140// wxGlCanvas
141//---------------------------------------------------------------------------
142
4660d7e5 143IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
8b089c5e 144
dc3065a5
VZ
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
b7ea712c 154 : m_createImplicitContext(false)
dc3065a5 155#endif
b7ea712c 156{
dc3065a5 157 Create(parent, id, pos, size, style, name, attribList, palette);
b7ea712c
RR
158}
159
dc3065a5
VZ
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)
b7ea712c 170 : m_createImplicitContext(true)
8b089c5e 171{
21562ad2
VZ
172 m_sharedContext = NULL;
173 m_sharedContextOf = NULL;
174
dc3065a5 175 Create(parent, id, pos, size, style, name, attribList, palette);
8b089c5e
JS
176}
177
dc3065a5
VZ
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)
b7ea712c 187 : m_createImplicitContext(true)
2b5f62a0 188{
5c33522f 189 m_sharedContext = const_cast<wxGLContext *>(shared);
dc3065a5
VZ
190
191 Create(parent, id, pos, size, style, name, attribList, palette);
8b089c5e
JS
192}
193
dc3065a5
VZ
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 )
b7ea712c 201 : m_createImplicitContext(true)
2b5f62a0 202{
21562ad2 203 m_sharedContext = NULL;
5c33522f 204 m_sharedContextOf = const_cast<wxGLCanvas *>(shared);
dc3065a5
VZ
205
206 Create(parent, id, pos, size, style, name, attribList, palette);
8b089c5e
JS
207}
208
dc3065a5 209#endif // WXWIN_COMPATIBILITY_2_8
2b5f62a0 210
dc3065a5
VZ
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,
9ce5cf09 218 const wxPalette& palette)
dc3065a5 219{
9ce5cf09 220#if wxUSE_PALETTE
9a83f860 221 wxASSERT_MSG( !palette.IsOk(), wxT("palettes not supported") );
9ce5cf09
VZ
222#endif // wxUSE_PALETTE
223 wxUnusedVar(palette); // Unused when wxDEBUG_LEVEL==0
e0d1fd7f 224
670f9935
WS
225 m_exposed = false;
226 m_noExpose = true;
227 m_nativeSizeEvent = true;
9dc44eff
PC
228#ifdef __WXGTK3__
229 m_cairoPaintContext = NULL;
230 m_backgroundStyle = wxBG_STYLE_PAINT;
231#endif
34a34b02 232
498ace9e
VZ
233 if ( !InitVisual(attribList) )
234 return false;
2b5f62a0 235
3780e252
PC
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);
2b5f62a0 241
ff654490 242 wxWindow::Create( parent, id, pos, size, style, name );
fee7a683 243
144ae5bb 244 gtk_widget_set_double_buffered(m_wxwindow, false);
2b5b9325 245
dc3065a5 246#if WXWIN_COMPATIBILITY_2_8
b7ea712c 247 g_signal_connect(m_wxwindow, "realize", G_CALLBACK(gtk_glwindow_realized_callback), this);
dc3065a5 248#endif // WXWIN_COMPATIBILITY_2_8
9dc44eff
PC
249#ifdef __WXGTK3__
250 g_signal_connect(m_wxwindow, "draw", G_CALLBACK(draw), this);
251#else
b7ea712c
RR
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);
9dc44eff 254#endif
b7ea712c 255 g_signal_connect(m_widget, "size_allocate", G_CALLBACK(gtk_glcanvas_size_callback), this);
a6f5aa49 256
dc3065a5 257#if WXWIN_COMPATIBILITY_2_8
bc869971
VZ
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
fc9ab22a 261 if (gtk_widget_get_realized(m_wxwindow))
bc869971 262 gtk_glwindow_realized_callback( m_wxwindow, this );
dc3065a5 263#endif // WXWIN_COMPATIBILITY_2_8
bc869971 264
9dc44eff 265#ifndef __WXGTK3__
fc9ab22a 266 if (gtk_widget_get_mapped(m_wxwindow))
bc869971 267 gtk_glwindow_map_callback( m_wxwindow, this );
9dc44eff 268#endif
bc869971 269
670f9935 270 return true;
a6f5aa49
VZ
271}
272
9dc44eff
PC
273bool wxGLCanvas::SetBackgroundStyle(wxBackgroundStyle /* style */)
274{
275 return false;
276}
277
498ace9e 278Window wxGLCanvas::GetXWindow() const
8b089c5e 279{
f089940f 280 GdkWindow* window = GTKGetDrawingWindow();
9dc44eff 281 return window ? GDK_WINDOW_XID(window) : 0;
8b089c5e
JS
282}
283
8b089c5e
JS
284void wxGLCanvas::OnInternalIdle()
285{
dc3065a5 286 if (m_exposed)
8b089c5e 287 {
9dc44eff
PC
288#ifdef __WXGTK3__
289 GTKSendPaintEvents(m_cairoPaintContext);
290 cairo_destroy(m_cairoPaintContext);
291 m_cairoPaintContext = NULL;
292#else
8b089c5e
JS
293 wxPaintEvent event( GetId() );
294 event.SetEventObject( this );
937013e0 295 HandleWindowEvent( event );
9dc44eff 296#endif
8b089c5e 297
670f9935 298 m_exposed = false;
8b089c5e
JS
299 GetUpdateRegion().Clear();
300 }
2b5f62a0 301
8b089c5e
JS
302 wxWindow::OnInternalIdle();
303}
304
dc3065a5
VZ
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}
a6f5aa49 318
dc3065a5 319#endif // WXWIN_COMPATIBILITY_2_8
a6f5aa49 320
dc3065a5 321#endif // wxUSE_GLCANVAS