]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/glcanvas.cpp
Ensure we don't modify a shared object in wxOSX wxRegion::DoOffset().
[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
7// RCS-ID: $Id$
8// Copyright: (c) Robert Roebling
65571936 9// Licence: wxWindows licence
8b089c5e
JS
10/////////////////////////////////////////////////////////////////////////////
11
14f355c2
VS
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
8b089c5e
JS
15#if wxUSE_GLCANVAS
16
17#include "wx/glcanvas.h"
18
a1abca32
PC
19#include <gtk/gtk.h>
20#include <gdk/gdkx.h>
86b8b3ac 21#include "wx/gtk/private/gtk2-compat.h"
8b089c5e 22
dc3065a5
VZ
23#if WXWIN_COMPATIBILITY_2_8
24
8b089c5e 25//-----------------------------------------------------------------------------
dc3065a5 26// "realize" from m_wxwindow: used to create m_glContext implicitly
8b089c5e
JS
27//-----------------------------------------------------------------------------
28
865bb325 29extern "C" {
144ae5bb 30static void
34a34b02 31gtk_glwindow_realized_callback( GtkWidget *WXUNUSED(widget), wxGLCanvas *win )
8b089c5e 32{
dc3065a5 33 win->GTKInitImplicitContext();
8b089c5e 34}
865bb325 35}
8b089c5e 36
dc3065a5
VZ
37#endif // WXWIN_COMPATIBILITY_2_8
38
8b089c5e
JS
39//-----------------------------------------------------------------------------
40// "map" from m_wxwindow
41//-----------------------------------------------------------------------------
42
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}
8b089c5e
JS
55
56//-----------------------------------------------------------------------------
57// "expose_event" of m_wxwindow
58//-----------------------------------------------------------------------------
59
865bb325 60extern "C" {
6d727f6c 61static gboolean
8b089c5e
JS
62gtk_glwindow_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxGLCanvas *win )
63{
670f9935 64 win->m_exposed = true;
8b089c5e
JS
65
66 win->GetUpdateRegion().Union( gdk_event->area.x,
67 gdk_event->area.y,
68 gdk_event->area.width,
69 gdk_event->area.height );
6d727f6c 70 return false;
8b089c5e 71}
865bb325 72}
8b089c5e 73
8b089c5e
JS
74//-----------------------------------------------------------------------------
75// "size_allocate" of m_wxwindow
76//-----------------------------------------------------------------------------
77
865bb325 78extern "C" {
2b5f62a0 79static void
e0d1fd7f
VZ
80gtk_glcanvas_size_callback(GtkWidget *WXUNUSED(widget),
81 GtkAllocation * WXUNUSED(alloc),
82 wxGLCanvas *win)
8b089c5e 83{
8b089c5e
JS
84 if (!win->m_hasVMT)
85 return;
86
87 wxSizeEvent event( wxSize(win->m_width,win->m_height), win->GetId() );
88 event.SetEventObject( win );
937013e0 89 win->HandleWindowEvent( event );
8b089c5e 90}
865bb325 91}
8b089c5e 92
3780e252
PC
93//-----------------------------------------------------------------------------
94// emission hook for "parent-set"
95//-----------------------------------------------------------------------------
96
97extern "C" {
98static gboolean
99parent_set_hook(GSignalInvocationHint*, guint, const GValue* param_values, void* data)
100{
101 wxGLCanvas* win = (wxGLCanvas*)data;
102 if (g_value_peek_pointer(&param_values[0]) == win->m_wxwindow)
103 {
104 const XVisualInfo* xvi = win->GetXVisualInfo();
105 GdkVisual* visual = gtk_widget_get_visual(win->m_wxwindow);
106 if (GDK_VISUAL_XVISUAL(visual)->visualid != xvi->visualid)
107 {
108 GdkScreen* screen = gtk_widget_get_screen(win->m_wxwindow);
109 visual = gdk_x11_screen_lookup_visual(screen, xvi->visualid);
110 GdkColormap* colormap = gdk_colormap_new(visual, false);
111 gtk_widget_set_colormap(win->m_wxwindow, colormap);
112 g_object_unref(colormap);
113 }
114 // remove hook
115 return false;
116 }
117 return true;
118}
119}
120
8b089c5e
JS
121//---------------------------------------------------------------------------
122// wxGlCanvas
123//---------------------------------------------------------------------------
124
4660d7e5 125IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
8b089c5e 126
dc3065a5
VZ
127wxGLCanvas::wxGLCanvas(wxWindow *parent,
128 wxWindowID id,
129 const int *attribList,
130 const wxPoint& pos,
131 const wxSize& size,
132 long style,
133 const wxString& name,
134 const wxPalette& palette)
135#if WXWIN_COMPATIBILITY_2_8
b7ea712c 136 : m_createImplicitContext(false)
dc3065a5 137#endif
b7ea712c 138{
dc3065a5 139 Create(parent, id, pos, size, style, name, attribList, palette);
b7ea712c
RR
140}
141
dc3065a5
VZ
142#if WXWIN_COMPATIBILITY_2_8
143
144wxGLCanvas::wxGLCanvas(wxWindow *parent,
145 wxWindowID id,
146 const wxPoint& pos,
147 const wxSize& size,
148 long style,
149 const wxString& name,
150 const int *attribList,
151 const wxPalette& palette)
b7ea712c 152 : m_createImplicitContext(true)
8b089c5e 153{
21562ad2
VZ
154 m_sharedContext = NULL;
155 m_sharedContextOf = NULL;
156
dc3065a5 157 Create(parent, id, pos, size, style, name, attribList, palette);
8b089c5e
JS
158}
159
dc3065a5
VZ
160wxGLCanvas::wxGLCanvas(wxWindow *parent,
161 const wxGLContext *shared,
162 wxWindowID id,
163 const wxPoint& pos,
164 const wxSize& size,
165 long style,
166 const wxString& name,
167 const int *attribList,
168 const wxPalette& palette)
b7ea712c 169 : m_createImplicitContext(true)
2b5f62a0 170{
5c33522f 171 m_sharedContext = const_cast<wxGLContext *>(shared);
dc3065a5
VZ
172
173 Create(parent, id, pos, size, style, name, attribList, palette);
8b089c5e
JS
174}
175
dc3065a5
VZ
176wxGLCanvas::wxGLCanvas(wxWindow *parent,
177 const wxGLCanvas *shared,
178 wxWindowID id,
179 const wxPoint& pos, const wxSize& size,
180 long style, const wxString& name,
181 const int *attribList,
182 const wxPalette& palette )
b7ea712c 183 : m_createImplicitContext(true)
2b5f62a0 184{
21562ad2 185 m_sharedContext = NULL;
5c33522f 186 m_sharedContextOf = const_cast<wxGLCanvas *>(shared);
dc3065a5
VZ
187
188 Create(parent, id, pos, size, style, name, attribList, palette);
8b089c5e
JS
189}
190
dc3065a5 191#endif // WXWIN_COMPATIBILITY_2_8
2b5f62a0 192
dc3065a5
VZ
193bool wxGLCanvas::Create(wxWindow *parent,
194 wxWindowID id,
195 const wxPoint& pos,
196 const wxSize& size,
197 long style,
198 const wxString& name,
199 const int *attribList,
9ce5cf09 200 const wxPalette& palette)
dc3065a5 201{
9ce5cf09 202#if wxUSE_PALETTE
9a83f860 203 wxASSERT_MSG( !palette.IsOk(), wxT("palettes not supported") );
9ce5cf09
VZ
204#endif // wxUSE_PALETTE
205 wxUnusedVar(palette); // Unused when wxDEBUG_LEVEL==0
e0d1fd7f 206
670f9935
WS
207 m_exposed = false;
208 m_noExpose = true;
209 m_nativeSizeEvent = true;
34a34b02 210
498ace9e
VZ
211 if ( !InitVisual(attribList) )
212 return false;
2b5f62a0 213
3780e252
PC
214 // watch for the "parent-set" signal on m_wxwindow so we can set colormap
215 // before m_wxwindow is realized (which will occur before
216 // wxWindow::Create() returns if parent is already visible)
217 unsigned sig_id = g_signal_lookup("parent-set", GTK_TYPE_WIDGET);
218 g_signal_add_emission_hook(sig_id, 0, parent_set_hook, this, NULL);
2b5f62a0 219
ff654490 220 wxWindow::Create( parent, id, pos, size, style, name );
fee7a683 221
144ae5bb 222 gtk_widget_set_double_buffered(m_wxwindow, false);
2b5b9325 223
dc3065a5 224#if WXWIN_COMPATIBILITY_2_8
b7ea712c 225 g_signal_connect(m_wxwindow, "realize", G_CALLBACK(gtk_glwindow_realized_callback), this);
dc3065a5 226#endif // WXWIN_COMPATIBILITY_2_8
b7ea712c
RR
227 g_signal_connect(m_wxwindow, "map", G_CALLBACK(gtk_glwindow_map_callback), this);
228 g_signal_connect(m_wxwindow, "expose_event", G_CALLBACK(gtk_glwindow_expose_callback), this);
229 g_signal_connect(m_widget, "size_allocate", G_CALLBACK(gtk_glcanvas_size_callback), this);
a6f5aa49 230
dc3065a5 231#if WXWIN_COMPATIBILITY_2_8
bc869971
VZ
232 // if our parent window is already visible, we had been realized before we
233 // connected to the "realize" signal and hence our m_glContext hasn't been
234 // initialized yet and we have to do it now
fc9ab22a 235 if (gtk_widget_get_realized(m_wxwindow))
bc869971 236 gtk_glwindow_realized_callback( m_wxwindow, this );
dc3065a5 237#endif // WXWIN_COMPATIBILITY_2_8
bc869971 238
fc9ab22a 239 if (gtk_widget_get_mapped(m_wxwindow))
bc869971
VZ
240 gtk_glwindow_map_callback( m_wxwindow, this );
241
670f9935 242 return true;
a6f5aa49
VZ
243}
244
498ace9e 245Window wxGLCanvas::GetXWindow() const
8b089c5e 246{
f089940f 247 GdkWindow* window = GTKGetDrawingWindow();
498ace9e 248 return window ? GDK_WINDOW_XWINDOW(window) : 0;
8b089c5e
JS
249}
250
8b089c5e
JS
251void wxGLCanvas::OnInternalIdle()
252{
dc3065a5 253 if (m_exposed)
8b089c5e
JS
254 {
255 wxPaintEvent event( GetId() );
256 event.SetEventObject( this );
937013e0 257 HandleWindowEvent( event );
8b089c5e 258
670f9935 259 m_exposed = false;
8b089c5e
JS
260 GetUpdateRegion().Clear();
261 }
2b5f62a0 262
8b089c5e
JS
263 wxWindow::OnInternalIdle();
264}
265
dc3065a5
VZ
266#if WXWIN_COMPATIBILITY_2_8
267
268void wxGLCanvas::GTKInitImplicitContext()
269{
270 if ( !m_glContext && m_createImplicitContext )
271 {
272 wxGLContext *share = m_sharedContext;
273 if ( !share && m_sharedContextOf )
274 share = m_sharedContextOf->m_glContext;
275
276 m_glContext = new wxGLContext(this, share);
277 }
278}
a6f5aa49 279
dc3065a5 280#endif // WXWIN_COMPATIBILITY_2_8
a6f5aa49 281
dc3065a5 282#endif // wxUSE_GLCANVAS