]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/glcanvas.cpp
Fix horizontal mouse wheel scrolling in wxGTK.
[wxWidgets.git] / src / gtk1 / glcanvas.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk1/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 #ifndef WX_PRECOMP
19 #include "wx/app.h"
20 #include "wx/frame.h"
21 #include "wx/colour.h"
22 #include "wx/module.h"
23 #endif // WX_PRECOMP
24
25 extern "C"
26 {
27 #include "gtk/gtk.h"
28 #include "gdk/gdk.h"
29 #include "gdk/gdkx.h"
30 }
31
32 #include "wx/gtk1/win_gtk.h"
33 #include "wx/gtk1/private.h"
34
35 //-----------------------------------------------------------------------------
36 // idle system
37 //-----------------------------------------------------------------------------
38
39 extern void wxapp_install_idle_handler();
40 extern bool g_isIdle;
41
42 #if WXWIN_COMPATIBILITY_2_8
43
44 //-----------------------------------------------------------------------------
45 // "realize" from m_wxwindow: used to create m_glContext implicitly
46 //-----------------------------------------------------------------------------
47
48 extern "C" {
49 static gint
50 gtk_glwindow_realized_callback( GtkWidget *WXUNUSED(widget), wxGLCanvas *win )
51 {
52 win->GTKInitImplicitContext();
53
54 return FALSE;
55 }
56 }
57
58 #endif // WXWIN_COMPATIBILITY_2_8
59
60 //-----------------------------------------------------------------------------
61 // "map" from m_wxwindow
62 //-----------------------------------------------------------------------------
63
64 extern "C" {
65 static gint
66 gtk_glwindow_map_callback( GtkWidget * WXUNUSED(widget), wxGLCanvas *win )
67 {
68 wxPaintEvent event( win->GetId() );
69 event.SetEventObject( win );
70 win->HandleWindowEvent( event );
71
72 win->GetUpdateRegion().Clear();
73
74 return FALSE;
75 }
76 }
77
78 //-----------------------------------------------------------------------------
79 // "expose_event" of m_wxwindow
80 //-----------------------------------------------------------------------------
81
82 extern "C" {
83 static void
84 gtk_glwindow_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxGLCanvas *win )
85 {
86 if (g_isIdle)
87 wxapp_install_idle_handler();
88
89 win->GetUpdateRegion().Union( gdk_event->area.x,
90 gdk_event->area.y,
91 gdk_event->area.width,
92 gdk_event->area.height );
93 }
94 }
95
96 //-----------------------------------------------------------------------------
97 // "draw" of m_wxwindow
98 //-----------------------------------------------------------------------------
99
100 extern "C" {
101 static void
102 gtk_glwindow_draw_callback( GtkWidget *WXUNUSED(widget), GdkRectangle *rect, wxGLCanvas *win )
103 {
104 if (g_isIdle)
105 wxapp_install_idle_handler();
106
107 win->GetUpdateRegion().Union( rect->x, rect->y,
108 rect->width, rect->height );
109 }
110 }
111
112 //-----------------------------------------------------------------------------
113 // "size_allocate" of m_wxwindow
114 //-----------------------------------------------------------------------------
115
116 extern "C" {
117 static void
118 gtk_glcanvas_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxGLCanvas *win )
119 {
120 if (g_isIdle)
121 wxapp_install_idle_handler();
122
123 if (!win->m_hasVMT)
124 return;
125
126 wxSizeEvent event( wxSize(win->m_width,win->m_height), win->GetId() );
127 event.SetEventObject( win );
128 win->HandleWindowEvent( event );
129 }
130 }
131
132 //---------------------------------------------------------------------------
133 // wxGlCanvas
134 //---------------------------------------------------------------------------
135
136 IMPLEMENT_CLASS(wxGLCanvas, wxWindow)
137
138 wxGLCanvas::wxGLCanvas(wxWindow *parent,
139 wxWindowID id,
140 const int *attribList,
141 const wxPoint& pos,
142 const wxSize& size,
143 long style,
144 const wxString& name,
145 const wxPalette& palette)
146 #if WXWIN_COMPATIBILITY_2_8
147 : m_createImplicitContext(false)
148 #endif
149 {
150 Create(parent, id, pos, size, style, name, attribList, palette);
151 }
152
153 #if WXWIN_COMPATIBILITY_2_8
154
155 wxGLCanvas::wxGLCanvas(wxWindow *parent,
156 wxWindowID id,
157 const wxPoint& pos,
158 const wxSize& size,
159 long style,
160 const wxString& name,
161 const int *attribList,
162 const wxPalette& palette)
163 : m_createImplicitContext(true)
164 {
165 Create(parent, id, pos, size, style, name, attribList, palette);
166 }
167
168 wxGLCanvas::wxGLCanvas(wxWindow *parent,
169 const wxGLContext *shared,
170 wxWindowID id,
171 const wxPoint& pos,
172 const wxSize& size,
173 long style,
174 const wxString& name,
175 const int *attribList,
176 const wxPalette& palette)
177 : m_createImplicitContext(true)
178 {
179 m_sharedContext = const_cast<wxGLContext *>(shared);
180
181 Create(parent, id, pos, size, style, name, attribList, palette);
182 }
183
184 wxGLCanvas::wxGLCanvas(wxWindow *parent,
185 const wxGLCanvas *shared,
186 wxWindowID id,
187 const wxPoint& pos, const wxSize& size,
188 long style, const wxString& name,
189 const int *attribList,
190 const wxPalette& palette )
191 : m_createImplicitContext(true)
192 {
193 m_sharedContextOf = const_cast<wxGLCanvas *>(shared);
194
195 Create(parent, id, pos, size, style, name, attribList, palette);
196 }
197
198 #endif // WXWIN_COMPATIBILITY_2_8
199
200 bool wxGLCanvas::Create(wxWindow *parent,
201 wxWindowID id,
202 const wxPoint& pos,
203 const wxSize& size,
204 long style,
205 const wxString& name,
206 const int *attribList,
207 const wxPalette& palette)
208 {
209 m_noExpose = true;
210 m_nativeSizeEvent = true;
211
212 if ( !InitVisual(attribList) )
213 return false;
214
215 GdkVisual *visual = gdkx_visual_get( GetXVisualInfo()->visualid );
216 GdkColormap *colormap = gdk_colormap_new( visual, TRUE );
217
218 gtk_widget_push_colormap( colormap );
219 gtk_widget_push_visual( visual );
220
221 wxWindow::Create( parent, id, pos, size, style, name );
222 m_glWidget = m_wxwindow;
223
224 gtk_pizza_set_clear( GTK_PIZZA(m_wxwindow), FALSE );
225
226 #if WXWIN_COMPATIBILITY_2_8
227 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
228 GTK_SIGNAL_FUNC(gtk_glwindow_realized_callback), (gpointer) this);
229 #endif // WXWIN_COMPATIBILITY_2_8
230
231 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "map",
232 GTK_SIGNAL_FUNC(gtk_glwindow_map_callback), (gpointer) this);
233
234 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
235 GTK_SIGNAL_FUNC(gtk_glwindow_expose_callback), (gpointer) this);
236
237 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
238 GTK_SIGNAL_FUNC(gtk_glwindow_draw_callback), (gpointer) this);
239
240 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
241 GTK_SIGNAL_FUNC(gtk_glcanvas_size_callback), (gpointer) this);
242
243 gtk_widget_pop_visual();
244
245 gtk_widget_pop_colormap();
246
247 #if WXWIN_COMPATIBILITY_2_8
248 // if our parent window is already visible, we had been realized before we
249 // connected to the "realize" signal and hence our m_glContext hasn't been
250 // initialized yet and we have to do it now
251 if (GTK_WIDGET_REALIZED(m_wxwindow))
252 gtk_glwindow_realized_callback( m_wxwindow, this );
253 #endif // WXWIN_COMPATIBILITY_2_8
254
255 if (GTK_WIDGET_MAPPED(m_wxwindow))
256 gtk_glwindow_map_callback( m_wxwindow, this );
257
258 return true;
259 }
260
261 Window wxGLCanvas::GetXWindow() const
262 {
263 GdkWindow *window = GTK_PIZZA(m_wxwindow)->bin_window;
264 return window ? GDK_WINDOW_XWINDOW(window) : 0;
265 }
266
267 void wxGLCanvas::OnInternalIdle()
268 {
269 if (!m_updateRegion.IsEmpty())
270 {
271 wxPaintEvent event( GetId() );
272 event.SetEventObject( this );
273 HandleWindowEvent( event );
274
275 GetUpdateRegion().Clear();
276 }
277
278 wxWindow::OnInternalIdle();
279 }
280
281 #if WXWIN_COMPATIBILITY_2_8
282
283 void wxGLCanvas::GTKInitImplicitContext()
284 {
285 if ( !m_glContext && m_createImplicitContext )
286 {
287 wxGLContext *share = m_sharedContext;
288 if ( !share && m_sharedContextOf )
289 share = m_sharedContextOf->m_glContext;
290
291 m_glContext = new wxGLContext(this, share);
292 }
293 }
294
295 #endif // WXWIN_COMPATIBILITY_2_8
296
297 #endif // wxUSE_GLCANVAS