comparison pidgin/plugins/crazychat/cc_gtk_gl.c @ 15374:5fe8042783c1

Rename gtk/ and libgaim/ to pidgin/ and libpurple/
author Sean Egan <seanegan@gmail.com>
date Sat, 20 Jan 2007 02:32:10 +0000
parents
children a8cc50c2279f
comparison
equal deleted inserted replaced
15373:f79e0f4df793 15374:5fe8042783c1
1 #include <assert.h>
2 #include <stdio.h>
3 #include <GL/gl.h>
4 #include <GL/glu.h>
5 #include "cc_gtk_gl.h"
6 #include "util.h"
7
8 static GdkGLConfig *glconfig = NULL;
9
10 /**
11 * Resets the OpenGL viewport stuff on widget reconfiguration (resize,
12 * reposition)
13 * @param widget widget that got reconfigured
14 * @param event the configuration event
15 * @param data unused
16 * @return FALSE to propagate other handlers
17 */
18 static gboolean configure_event(GtkWidget *widget, GdkEventConfigure *event,
19 void *data);
20
21 /**
22 * Maps the widget to the screen.
23 * @param widget widget that got mapped
24 * @param event the map event
25 * @param data draw info struct
26 * @return FALSE to propagate other handlers
27 */
28 static gboolean map_event(GtkWidget *widget, GdkEventAny *event, void *data);
29
30 /**
31 * Unmaps the widget from the screen.
32 * @param widget widget that got unmapped
33 * @param event the configuration event
34 * @param data draw info struct
35 * @return FALSE to propagate other handlers
36 */
37 static gboolean unmap_event(GtkWidget *widget, GdkEventAny *event, void *data);
38
39 /**
40 * Respond to widget visibility change.
41 * @param widget widget whose visibility changed
42 * @param event the visibility event
43 * @param data draw info struct
44 * @return FALSE to propagate other handlers
45 */
46 static gboolean visibility_notify_event(GtkWidget *widget,
47 GdkEventVisibility *event, void *data);
48
49 /**
50 * Add a glib timer to periodically draw the widget.
51 * @param widget widget we're drawing
52 * @param info draw info struct
53 */
54 static void widget_draw_timer_add(GtkWidget *widget, struct draw_info *info);
55
56 /**
57 * Remove glib timer that was drawing this widget.
58 * @param widget widget we're drawing
59 * @param info draw info struct
60 */
61 static void widget_draw_timer_remove(GtkWidget *widget, struct draw_info *info);
62
63 /**
64 * Periodically invalidates gtk gl widget and tells GTK to redraw
65 * @param widget widget we're drawing
66 */
67 static gboolean widget_draw_timer(GtkWidget *widget);
68
69 /**
70 * Cleanup widget stuff when it's getting destroyed.
71 * @param widget widget that got destroyed
72 * @param data draw info struct
73 */
74 static void destroy_event(GtkWidget *widget, struct draw_info *data);
75
76 int cc_init_gtk_gl()
77 {
78 if (glconfig)
79 return 0;
80
81 /* configure OpenGL */
82
83 glconfig = gdk_gl_config_new_by_mode(GDK_GL_MODE_RGB |
84 GDK_GL_MODE_DEPTH |
85 GDK_GL_MODE_DOUBLE);
86
87 if (glconfig == NULL) {
88 Debug("*** Cannot find the double-buffered visual.\n");
89 Debug("*** Trying single-buffered visual.\n");
90
91 /* Try single-buffered visual */
92 glconfig = gdk_gl_config_new_by_mode(GDK_GL_MODE_RGB |
93 GDK_GL_MODE_DEPTH);
94 if (glconfig == NULL) {
95 Debug("*** No appropriate OpenGL-capable visual "
96 "found.\n");
97 return 1;
98 }
99 }
100
101 return 0;
102 }
103
104 void cc_new_gl_window(gl_init_func init, gl_config_func config,
105 gl_draw_func draw, struct draw_info *data,
106 struct window_box *ret)
107 {
108 GtkWidget *window;
109 GtkWidget *vbox;
110 GtkWidget *drawing_area;
111
112 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
113 gtk_container_set_reallocate_redraws(GTK_CONTAINER(window), TRUE);
114
115 vbox = gtk_vbox_new(FALSE, 0);
116 gtk_container_add(GTK_CONTAINER(window), vbox);
117 gtk_widget_show(vbox);
118
119 if (!data) {
120 data = (struct draw_info*)malloc(sizeof(*data));
121 assert(data);
122 memset(data, 0, sizeof(*data));
123 data->timeout = TRUE;
124 data->delay_ms = DEFAULT_FRAME_DELAY;
125 }
126 drawing_area = cc_new_gl_area(init, config, draw, data);
127 gtk_box_pack_start(GTK_BOX(vbox), drawing_area, TRUE, TRUE, 0);
128 gtk_widget_show(drawing_area);
129 ret->window = window;
130 ret->vbox = vbox;
131 ret->draw_area = drawing_area;
132 }
133
134 GtkWidget *cc_new_gl_area(gl_init_func init, gl_config_func config,
135 gl_draw_func draw, struct draw_info *data)
136 {
137 GtkWidget *drawing_area;
138
139 assert(data);
140
141 drawing_area = gtk_drawing_area_new();
142 assert(drawing_area);
143
144 assert(gtk_widget_set_gl_capability(drawing_area, glconfig, NULL, FALSE,
145 GDK_GL_RGBA_TYPE));
146 gtk_widget_add_events (drawing_area, GDK_VISIBILITY_NOTIFY_MASK);
147 if (init) {
148 g_signal_connect_after(G_OBJECT(drawing_area), "realize",
149 G_CALLBACK(init), data->data);
150 }
151 if (config) {
152 g_signal_connect(G_OBJECT(drawing_area), "configure_event",
153 G_CALLBACK(config), NULL);
154 } else {
155 g_signal_connect(G_OBJECT(drawing_area), "configure_event",
156 G_CALLBACK(configure_event), NULL);
157 }
158 if (draw) {
159 g_signal_connect(G_OBJECT(drawing_area), "expose_event",
160 G_CALLBACK(draw), data->data);
161 }
162 g_signal_connect(G_OBJECT(drawing_area), "map_event",
163 G_CALLBACK(map_event), data);
164 g_signal_connect(G_OBJECT(drawing_area), "unmap_event",
165 G_CALLBACK(unmap_event), data);
166 g_signal_connect(G_OBJECT(drawing_area), "visibility_notify_event",
167 G_CALLBACK(visibility_notify_event), data);
168 g_signal_connect(G_OBJECT(drawing_area), "destroy",
169 G_CALLBACK(destroy_event), data);
170
171 return drawing_area;
172 }
173
174
175 static gboolean configure_event(GtkWidget *widget,
176 GdkEventConfigure *event, void *data)
177 {
178 GdkGLContext *glcontext = gtk_widget_get_gl_context(widget);
179 GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
180
181 GLfloat w = widget->allocation.width;
182 GLfloat h = widget->allocation.height;
183 GLfloat aspect;
184
185 // Debug("configuring\n");
186
187 /*** OpenGL BEGIN ***/
188 if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
189 return FALSE;
190
191 glViewport(0, 0, w, h);
192 glMatrixMode(GL_PROJECTION);
193
194 glLoadIdentity();
195 if (w > h) {
196 aspect = w / h;
197 glFrustum(-aspect, aspect, -1.0, 1.0, 2.0, 60.0);
198 } else {
199 aspect = h / w;
200 glFrustum(-1.0, 1.0, -aspect, aspect, 2.0, 60.0);
201 }
202 glMatrixMode(GL_MODELVIEW);
203 glLoadIdentity();
204
205 gdk_gl_drawable_gl_end(gldrawable);
206 /*** OpenGL END ***/
207
208 return FALSE;
209 }
210
211 static int map_event(GtkWidget *widget, GdkEventAny *event, void *data)
212 {
213 struct draw_info *info = (struct draw_info*)data;
214 Debug("map\n");
215
216 if (info->timeout) {
217 widget_draw_timer_add(widget, info);
218 }
219 return FALSE;
220 }
221
222 static int unmap_event(GtkWidget *widget, GdkEventAny *event, void *data)
223 {
224 struct draw_info *info = (struct draw_info*)data;
225 Debug("unmap\n");
226
227 if (info->timeout) {
228 widget_draw_timer_remove(widget, info);
229 }
230 return FALSE;
231 }
232
233 static int visibility_notify_event(GtkWidget *widget, GdkEventVisibility *event,
234 void *data)
235 {
236 struct draw_info *info = (struct draw_info*)data;
237 Debug("visibility\n");
238
239 if (event->state == GDK_VISIBILITY_FULLY_OBSCURED) {
240 Debug("obscured\n");
241 if (info->timeout) {
242 widget_draw_timer_remove(widget, info);
243 }
244 } else {
245 Debug("visible\n");
246 if (info->timeout) {
247 widget_draw_timer_add(widget, info);
248 }
249 }
250 return FALSE;
251 }
252
253 static void widget_draw_timer_add(GtkWidget *widget, struct draw_info *info)
254 {
255 if (!info->timer_id) {
256 info->timer_id = g_timeout_add(info->delay_ms,
257 (GSourceFunc)widget_draw_timer, widget);
258 }
259 }
260
261 static void widget_draw_timer_remove(GtkWidget *widget, struct draw_info *info)
262 {
263 if (info->timer_id) {
264 g_source_remove(info->timer_id);
265 info->timer_id = 0;
266 }
267 }
268
269 static gboolean widget_draw_timer(GtkWidget *widget)
270 {
271 /* invalidate the window */
272 gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
273
274 /* tell gtk to update it _now_ */
275 gdk_window_process_updates (widget->window, FALSE);
276
277 return TRUE;
278 }
279
280 static void destroy_event(GtkWidget *widget, struct draw_info *data)
281 {
282 Debug("destroying widget\n");
283
284 if (data) {
285 widget_draw_timer_remove(widget, data);
286 free(data);
287 }
288 }