glut2 8.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,845 @@
1
+ #include "common.h"
2
+
3
+ /* HACK experimental API */
4
+ void *rb_thread_call_with_gvl(void *(*func)(void *), void *data1);
5
+
6
+ static ID call_id; /* 'call' method id */
7
+ static VALUE idle_func = Qnil;
8
+ static VALUE joystick_func = Qnil;
9
+ static VALUE menustate_func = Qnil;
10
+ static VALUE menustatus_func = Qnil;
11
+ static VALUE timer_func = Qnil;
12
+
13
+ typedef void *(*gvl_call)(void *);
14
+
15
+ struct callback_args {
16
+ union {
17
+ int button;
18
+ int dial;
19
+ int special;
20
+ int state;
21
+ int value;
22
+ int width;
23
+ int x;
24
+ unsigned char key;
25
+ unsigned int button_mask;
26
+ } arg0;
27
+ union {
28
+ int height;
29
+ int state;
30
+ int value;
31
+ int x;
32
+ int y;
33
+ } arg1;
34
+ union {
35
+ int x;
36
+ int y;
37
+ int z;
38
+ } arg2;
39
+ union {
40
+ int y;
41
+ int z;
42
+ } arg3;
43
+ } ;
44
+
45
+ static struct callback_args *
46
+ alloc_callback_args(void) {
47
+ struct callback_args *args;
48
+ args = (struct callback_args *)malloc(sizeof(struct callback_args));
49
+
50
+ if (args == NULL) {
51
+ fprintf(stderr, "[BUG] out of memory in opengl callback");
52
+ abort();
53
+ }
54
+
55
+ return args;
56
+ }
57
+
58
+ /*
59
+ * macros for registering callbacks -
60
+ *
61
+ * most GLUT callback functions are part of specific window state, so
62
+ * the same callback may have different functions for each GLUT window
63
+ *
64
+ * callbacks that are not tied to specific window (idle,timer,menustate) are
65
+ * registered manually
66
+ */
67
+
68
+ #define WINDOW_CALLBACK_SETUP(_funcname) \
69
+ static VALUE _funcname = Qnil; \
70
+ static VALUE \
71
+ glut_ ## _funcname(VALUE self, VALUE callback) \
72
+ { \
73
+ int win = glutGetWindow(); \
74
+ \
75
+ if (win == 0) { \
76
+ rb_raise(rb_eRuntimeError, "glut%s needs current window", #_funcname); \
77
+ } \
78
+ \
79
+ callback = rb_glut_check_callback(self, callback); \
80
+ \
81
+ rb_ary_store(_funcname, win, callback); \
82
+ \
83
+ if (NIL_P(callback)) \
84
+ glut##_funcname(NULL); \
85
+ else \
86
+ glut##_funcname(&glut_##_funcname##Callback0); \
87
+ \
88
+ return Qnil; \
89
+ }
90
+
91
+ #define WINDOW_CALLBACK_DEFINE(module, _funcname) \
92
+ rb_define_module_function(module, "glut"#_funcname, glut_##_funcname, 1); \
93
+ rb_global_variable(&_funcname); \
94
+ _funcname = rb_ary_new()
95
+
96
+ static void GLUTCALLBACK glut_DisplayFuncCallback0(void);
97
+ static void GLUTCALLBACK glut_ReshapeFuncCallback0(int, int);
98
+ static void GLUTCALLBACK glut_KeyboardFuncCallback0(unsigned char, int, int);
99
+ static void GLUTCALLBACK glut_MouseFuncCallback0(int, int, int, int);
100
+ static void GLUTCALLBACK glut_MotionFuncCallback0(int, int);
101
+ static void GLUTCALLBACK glut_PassiveMotionFuncCallback0(int, int);
102
+ static void GLUTCALLBACK glut_EntryFuncCallback0(int);
103
+ static void GLUTCALLBACK glut_VisibilityFuncCallback0(int);
104
+ static void GLUTCALLBACK glut_SpecialFuncCallback0(int, int, int);
105
+ static void GLUTCALLBACK glut_SpaceballMotionFuncCallback0(int, int, int);
106
+ static void GLUTCALLBACK glut_SpaceballRotateFuncCallback0(int, int, int);
107
+ static void GLUTCALLBACK glut_SpaceballButtonFuncCallback0(int, int);
108
+ static void GLUTCALLBACK glut_ButtonBoxFuncCallback0(int, int);
109
+ static void GLUTCALLBACK glut_DialsFuncCallback0(int, int);
110
+ static void GLUTCALLBACK glut_TabletMotionFuncCallback0(int, int);
111
+ static void GLUTCALLBACK glut_TabletButtonFuncCallback0(int, int, int, int);
112
+ static void GLUTCALLBACK glut_OverlayDisplayFuncCallback0(void);
113
+ static void GLUTCALLBACK glut_WindowStatusFuncCallback0(int);
114
+ static void GLUTCALLBACK glut_JoystickFuncCallback0(unsigned int, int, int, int);
115
+ static void GLUTCALLBACK glut_KeyboardUpFuncCallback0(unsigned char, int, int);
116
+ static void GLUTCALLBACK glut_SpecialUpFuncCallback0(int, int, int);
117
+
118
+ WINDOW_CALLBACK_SETUP(DisplayFunc)
119
+ WINDOW_CALLBACK_SETUP(ReshapeFunc)
120
+ WINDOW_CALLBACK_SETUP(KeyboardFunc)
121
+ WINDOW_CALLBACK_SETUP(MouseFunc)
122
+ WINDOW_CALLBACK_SETUP(MotionFunc)
123
+ WINDOW_CALLBACK_SETUP(PassiveMotionFunc)
124
+ WINDOW_CALLBACK_SETUP(EntryFunc)
125
+ WINDOW_CALLBACK_SETUP(VisibilityFunc)
126
+ WINDOW_CALLBACK_SETUP(SpecialFunc)
127
+ WINDOW_CALLBACK_SETUP(SpaceballMotionFunc)
128
+ WINDOW_CALLBACK_SETUP(SpaceballRotateFunc)
129
+ WINDOW_CALLBACK_SETUP(SpaceballButtonFunc)
130
+ WINDOW_CALLBACK_SETUP(ButtonBoxFunc)
131
+ WINDOW_CALLBACK_SETUP(DialsFunc)
132
+ WINDOW_CALLBACK_SETUP(TabletMotionFunc)
133
+ WINDOW_CALLBACK_SETUP(TabletButtonFunc)
134
+ WINDOW_CALLBACK_SETUP(OverlayDisplayFunc)
135
+ WINDOW_CALLBACK_SETUP(WindowStatusFunc)
136
+ WINDOW_CALLBACK_SETUP(KeyboardUpFunc)
137
+ WINDOW_CALLBACK_SETUP(SpecialUpFunc)
138
+
139
+ GLUT_SIMPLE_FUNCTION(ForceJoystickFunc)
140
+
141
+ static void *
142
+ glut_DisplayFuncCallback(void *ignored) {
143
+ VALUE func;
144
+
145
+ func = rb_ary_entry(DisplayFunc, glutGetWindow());
146
+
147
+ if (!NIL_P(func))
148
+ rb_funcall(func, call_id, 0);
149
+
150
+ return NULL;
151
+ }
152
+
153
+ static void GLUTCALLBACK
154
+ glut_DisplayFuncCallback0(void) {
155
+ rb_thread_call_with_gvl(glut_DisplayFuncCallback, NULL);
156
+ }
157
+
158
+ static void *
159
+ glut_ReshapeFuncCallback(struct callback_args *args) {
160
+ VALUE func = rb_ary_entry(ReshapeFunc, glutGetWindow());
161
+ VALUE width = INT2FIX(args->arg0.width);
162
+ VALUE height = INT2FIX(args->arg1.height);
163
+
164
+ if (!NIL_P(func))
165
+ rb_funcall(func, call_id, 2, width, height);
166
+
167
+ return NULL;
168
+ }
169
+
170
+ static void GLUTCALLBACK
171
+ glut_ReshapeFuncCallback0(int width, int height) {
172
+ struct callback_args *args = alloc_callback_args();
173
+
174
+ args->arg0.width = width;
175
+ args->arg1.height = height;
176
+
177
+ rb_thread_call_with_gvl((gvl_call)glut_ReshapeFuncCallback, args);
178
+
179
+ free(args);
180
+ }
181
+
182
+ static void *
183
+ glut_KeyboardFuncCallback(struct callback_args *args) {
184
+ VALUE func = rb_ary_entry(KeyboardFunc, glutGetWindow());
185
+ #if HAVE_SINGLE_BYTE_STRINGS
186
+ VALUE key = rb_str_new((char *)&args->arg0.key, 1);
187
+ #else
188
+ VALUE key = UINT2NUM((unsigned char)args->arg0.key);
189
+ #endif
190
+ VALUE x = INT2FIX(args->arg1.x);
191
+ VALUE y = INT2FIX(args->arg2.y);
192
+
193
+ if (!NIL_P(func))
194
+ rb_funcall(func, call_id, 3, key, x, y);
195
+
196
+ return NULL;
197
+ }
198
+
199
+ static void GLUTCALLBACK
200
+ glut_KeyboardFuncCallback0(unsigned char key, int x, int y) {
201
+ struct callback_args *args = alloc_callback_args();
202
+
203
+ args->arg0.key = key;
204
+ args->arg1.x = x;
205
+ args->arg2.y = y;
206
+
207
+ rb_thread_call_with_gvl((gvl_call)glut_KeyboardFuncCallback, args);
208
+
209
+ free(args);
210
+ }
211
+
212
+ static void *
213
+ glut_KeyboardUpFuncCallback(struct callback_args *args) {
214
+ VALUE func = rb_ary_entry(KeyboardUpFunc, glutGetWindow());
215
+ #if HAVE_SINGLE_BYTE_STRINGS
216
+ VALUE key = rb_str_new((char *)&args->arg0.key, 1);
217
+ #else
218
+ VALUE key = UINT2NUM((unsigned char)args->arg0.key);
219
+ #endif
220
+ VALUE x = INT2FIX(args->arg1.x);
221
+ VALUE y = INT2FIX(args->arg2.y);
222
+
223
+ if (!NIL_P(func))
224
+ rb_funcall(func, call_id, 3, key, x, y);
225
+
226
+ return NULL;
227
+ }
228
+
229
+ static void GLUTCALLBACK
230
+ glut_KeyboardUpFuncCallback0(unsigned char key, int x, int y) {
231
+ struct callback_args *args = alloc_callback_args();
232
+
233
+ args->arg0.key = key;
234
+ args->arg1.x = x;
235
+ args->arg2.y = y;
236
+
237
+ rb_thread_call_with_gvl((gvl_call)glut_KeyboardUpFuncCallback, args);
238
+
239
+ free(args);
240
+ }
241
+
242
+ static void *
243
+ glut_MouseFuncCallback(struct callback_args *args) {
244
+ VALUE func = rb_ary_entry(MouseFunc, glutGetWindow());
245
+
246
+ VALUE button = INT2FIX(args->arg0.button);
247
+ VALUE state = INT2FIX(args->arg1.state);
248
+ VALUE x = INT2FIX(args->arg2.x);
249
+ VALUE y = INT2FIX(args->arg3.y);
250
+
251
+ if (!NIL_P(func))
252
+ rb_funcall(func, call_id, 4, button, state, x, y);
253
+
254
+ return NULL;
255
+ }
256
+
257
+ static void GLUTCALLBACK
258
+ glut_MouseFuncCallback0(int button, int state, int x, int y) {
259
+ struct callback_args *args = alloc_callback_args();
260
+
261
+ args->arg0.button = button;
262
+ args->arg1.state = state;
263
+ args->arg2.x = x;
264
+ args->arg3.y = y;
265
+
266
+ rb_thread_call_with_gvl((gvl_call)glut_MouseFuncCallback, args);
267
+
268
+ free(args);
269
+ }
270
+
271
+ static void *
272
+ glut_MotionFuncCallback(struct callback_args *args) {
273
+ VALUE func = rb_ary_entry(MotionFunc, glutGetWindow());
274
+ VALUE x = INT2FIX(args->arg0.x);
275
+ VALUE y = INT2FIX(args->arg1.y);
276
+
277
+ if (!NIL_P(func))
278
+ rb_funcall(func, call_id, 2, x, y);
279
+
280
+ return NULL;
281
+ }
282
+
283
+ static void GLUTCALLBACK
284
+ glut_MotionFuncCallback0(int x, int y) {
285
+ struct callback_args *args = alloc_callback_args();
286
+
287
+ args->arg0.x = x;
288
+ args->arg1.y = y;
289
+
290
+ rb_thread_call_with_gvl((gvl_call)glut_MotionFuncCallback, args);
291
+
292
+ free(args);
293
+ }
294
+
295
+ static void *
296
+ glut_PassiveMotionFuncCallback(struct callback_args *args) {
297
+ VALUE func = rb_ary_entry(PassiveMotionFunc, glutGetWindow());
298
+ VALUE x = INT2FIX(args->arg0.x);
299
+ VALUE y = INT2FIX(args->arg1.y);
300
+
301
+ if (!NIL_P(func))
302
+ rb_funcall(func, call_id, 2, x, y);
303
+
304
+ return NULL;
305
+ }
306
+
307
+ static void GLUTCALLBACK
308
+ glut_PassiveMotionFuncCallback0(int x, int y) {
309
+ struct callback_args *args = alloc_callback_args();
310
+
311
+ args->arg0.x = x;
312
+ args->arg1.y = y;
313
+
314
+ rb_thread_call_with_gvl((gvl_call)glut_PassiveMotionFuncCallback, args);
315
+
316
+ free(args);
317
+ }
318
+
319
+ static void *
320
+ glut_EntryFuncCallback(struct callback_args *args) {
321
+ VALUE func = rb_ary_entry(EntryFunc, glutGetWindow());
322
+ VALUE state = INT2NUM(args->arg0.state);
323
+
324
+ if (!NIL_P(func))
325
+ rb_funcall(func, call_id, 1, state);
326
+
327
+ return NULL;
328
+ }
329
+
330
+ static void GLUTCALLBACK
331
+ glut_EntryFuncCallback0(int state) {
332
+ struct callback_args *args = alloc_callback_args();
333
+
334
+ args->arg0.state = state;
335
+
336
+ rb_thread_call_with_gvl((gvl_call)glut_EntryFuncCallback, args);
337
+
338
+ free(args);
339
+ }
340
+
341
+ static void *
342
+ glut_VisibilityFuncCallback(struct callback_args *args) {
343
+ VALUE func = rb_ary_entry(VisibilityFunc, glutGetWindow());
344
+ VALUE state = INT2NUM(args->arg0.state);
345
+
346
+ if (!NIL_P(func))
347
+ rb_funcall(func, call_id, 1, state);
348
+
349
+ return NULL;
350
+ }
351
+
352
+ static void GLUTCALLBACK
353
+ glut_VisibilityFuncCallback0(int state) {
354
+ struct callback_args *args = alloc_callback_args();
355
+
356
+ args->arg0.state = state;
357
+
358
+ rb_thread_call_with_gvl((gvl_call)glut_VisibilityFuncCallback, args);
359
+
360
+ free(args);
361
+ }
362
+
363
+ static void *
364
+ glut_IdleFuncCallback(void *ignored) {
365
+ if (!NIL_P(idle_func))
366
+ rb_funcall(idle_func, call_id, 0);
367
+
368
+ return NULL;
369
+ }
370
+
371
+ static void GLUTCALLBACK
372
+ glut_IdleFuncCallback0(void) {
373
+ rb_thread_call_with_gvl((gvl_call)glut_IdleFuncCallback, NULL);
374
+ }
375
+
376
+ static void *
377
+ glut_TimerFuncCallback(struct callback_args *args) {
378
+ VALUE value = INT2NUM(args->arg0.value);
379
+
380
+ if (!NIL_P(timer_func))
381
+ rb_funcall(timer_func, call_id, 1, value);
382
+
383
+ return NULL;
384
+ }
385
+
386
+ static void GLUTCALLBACK
387
+ glut_TimerFuncCallback0(int value) {
388
+ struct callback_args *args = alloc_callback_args();
389
+
390
+ args->arg0.value = value;
391
+
392
+ rb_thread_call_with_gvl((gvl_call)glut_TimerFuncCallback, args);
393
+
394
+ free(args);
395
+ }
396
+
397
+ static void *
398
+ glut_MenuStateFuncCallback(struct callback_args *args) {
399
+ VALUE state = INT2NUM(args->arg0.state);
400
+
401
+ if (!NIL_P(menustate_func))
402
+ rb_funcall(menustate_func, call_id, 1, state);
403
+
404
+ return NULL;
405
+ }
406
+
407
+ static void GLUTCALLBACK
408
+ glut_MenuStateFuncCallback0(int state) {
409
+ struct callback_args *args = alloc_callback_args();
410
+
411
+ args->arg0.state = state;
412
+
413
+ rb_thread_call_with_gvl((gvl_call)glut_MenuStateFuncCallback, args);
414
+
415
+ free(args);
416
+ }
417
+
418
+ static void *
419
+ glut_MenuStatusFuncCallback(struct callback_args *args) {
420
+ VALUE state = INT2NUM(args->arg0.state);
421
+ VALUE x = INT2NUM(args->arg1.x);
422
+ VALUE y = INT2NUM(args->arg2.y);
423
+
424
+ if (!NIL_P(menustatus_func))
425
+ rb_funcall(menustatus_func, call_id, 3, state, x, y);
426
+
427
+ return NULL;
428
+ }
429
+
430
+ static void GLUTCALLBACK
431
+ glut_MenuStatusFuncCallback0(int state, int x, int y) {
432
+ struct callback_args *args = alloc_callback_args();
433
+
434
+ args->arg0.state = state;
435
+ args->arg1.x = x;
436
+ args->arg2.y = y;
437
+
438
+ rb_thread_call_with_gvl((gvl_call)glut_MenuStatusFuncCallback, args);
439
+
440
+ free(args);
441
+ }
442
+
443
+ static void *
444
+ glut_SpecialFuncCallback(struct callback_args *args) {
445
+ VALUE func = rb_ary_entry(SpecialFunc, glutGetWindow());
446
+ VALUE key = INT2NUM(args->arg0.key);
447
+ VALUE x = INT2NUM(args->arg1.x);
448
+ VALUE y = INT2NUM(args->arg2.y);
449
+
450
+ if (!NIL_P(func))
451
+ rb_funcall(func, call_id, 3, key, x, y);
452
+
453
+ return NULL;
454
+ }
455
+
456
+ static void GLUTCALLBACK
457
+ glut_SpecialFuncCallback0(int key, int x, int y) {
458
+ struct callback_args *args = alloc_callback_args();
459
+
460
+ args->arg0.key = key;
461
+ args->arg1.x = x;
462
+ args->arg2.y = y;
463
+
464
+ rb_thread_call_with_gvl((gvl_call)glut_SpecialFuncCallback, args);
465
+
466
+ free(args);
467
+ }
468
+
469
+ static void *
470
+ glut_SpecialUpFuncCallback(struct callback_args *args) {
471
+ VALUE func = rb_ary_entry(SpecialUpFunc, glutGetWindow());
472
+ VALUE key = INT2NUM(args->arg0.key);
473
+ VALUE x = INT2NUM(args->arg1.x);
474
+ VALUE y = INT2NUM(args->arg2.y);
475
+
476
+ if (!NIL_P(func))
477
+ rb_funcall(func, call_id, 3, key, x, y);
478
+
479
+ return NULL;
480
+ }
481
+
482
+ static void GLUTCALLBACK
483
+ glut_SpecialUpFuncCallback0(int key, int x, int y) {
484
+ struct callback_args *args = alloc_callback_args();
485
+
486
+ args->arg0.key = key;
487
+ args->arg1.x = x;
488
+ args->arg2.y = y;
489
+
490
+ rb_thread_call_with_gvl((gvl_call)glut_SpecialUpFuncCallback, args);
491
+
492
+ free(args);
493
+ }
494
+
495
+ static void *
496
+ glut_SpaceballMotionFuncCallback(struct callback_args *args) {
497
+ VALUE func = rb_ary_entry(SpaceballMotionFunc, glutGetWindow());
498
+ VALUE x = INT2NUM(args->arg0.x);
499
+ VALUE y = INT2NUM(args->arg1.y);
500
+ VALUE z = INT2NUM(args->arg2.z);
501
+
502
+ if (!NIL_P(func))
503
+ rb_funcall(func, call_id, 3, x, y, z);
504
+
505
+ return NULL;
506
+ }
507
+
508
+ static void GLUTCALLBACK
509
+ glut_SpaceballMotionFuncCallback0(int x, int y, int z) {
510
+ struct callback_args *args = alloc_callback_args();
511
+
512
+ args->arg0.x = x;
513
+ args->arg1.y = y;
514
+ args->arg2.z = z;
515
+
516
+ rb_thread_call_with_gvl((gvl_call)glut_SpaceballMotionFuncCallback, args);
517
+
518
+ free(args);
519
+ }
520
+
521
+ static void *
522
+ glut_SpaceballRotateFuncCallback(struct callback_args *args) {
523
+ VALUE func = rb_ary_entry(SpaceballRotateFunc, glutGetWindow());
524
+ VALUE x = INT2NUM(args->arg0.x);
525
+ VALUE y = INT2NUM(args->arg1.y);
526
+ VALUE z = INT2NUM(args->arg2.z);
527
+
528
+ if (!NIL_P(func))
529
+ rb_funcall(func, call_id, 3, x, y, z);
530
+
531
+ return NULL;
532
+ }
533
+
534
+ static void GLUTCALLBACK
535
+ glut_SpaceballRotateFuncCallback0(int x, int y, int z) {
536
+ struct callback_args *args = alloc_callback_args();
537
+
538
+ args->arg0.x = x;
539
+ args->arg1.y = y;
540
+ args->arg2.z = z;
541
+
542
+ rb_thread_call_with_gvl((gvl_call)glut_SpaceballRotateFuncCallback, args);
543
+
544
+ free(args);
545
+ }
546
+
547
+ static void *
548
+ glut_SpaceballButtonFuncCallback(struct callback_args *args) {
549
+ VALUE func = rb_ary_entry(SpaceballButtonFunc, glutGetWindow());
550
+ VALUE button = INT2NUM(args->arg0.button);
551
+ VALUE state = INT2NUM(args->arg1.state);
552
+
553
+ if (!NIL_P(func))
554
+ rb_funcall(func, call_id, 2, button, state);
555
+
556
+ return NULL;
557
+ }
558
+
559
+ static void GLUTCALLBACK
560
+ glut_SpaceballButtonFuncCallback0(int button, int state) {
561
+ struct callback_args *args = alloc_callback_args();
562
+
563
+ args->arg0.button = button;
564
+ args->arg1.state = state;
565
+
566
+ rb_thread_call_with_gvl((gvl_call)glut_SpaceballButtonFuncCallback, args);
567
+
568
+ free(args);
569
+ }
570
+
571
+ static void *
572
+ glut_ButtonBoxFuncCallback(struct callback_args *args) {
573
+ VALUE func = rb_ary_entry(ButtonBoxFunc, glutGetWindow());
574
+ VALUE button = INT2NUM(args->arg0.button);
575
+ VALUE state = INT2NUM(args->arg1.state);
576
+
577
+ if (!NIL_P(func))
578
+ rb_funcall(func, call_id, 2, button, state);
579
+
580
+ return NULL;
581
+ }
582
+
583
+ static void GLUTCALLBACK
584
+ glut_ButtonBoxFuncCallback0(int button, int state) {
585
+ struct callback_args *args = alloc_callback_args();
586
+
587
+ args->arg0.button = button;
588
+ args->arg1.state = state;
589
+
590
+ rb_thread_call_with_gvl((gvl_call)glut_ButtonBoxFuncCallback, args);
591
+
592
+ free(args);
593
+ }
594
+
595
+ static void *
596
+ glut_DialsFuncCallback(struct callback_args *args) {
597
+ VALUE func = rb_ary_entry(DialsFunc, glutGetWindow());
598
+ VALUE dial = INT2NUM(args->arg0.dial);
599
+ VALUE value = INT2NUM(args->arg1.value);
600
+
601
+ if (!NIL_P(func))
602
+ rb_funcall(func, call_id, 2, dial, value);
603
+
604
+ return NULL;
605
+ }
606
+
607
+ static void GLUTCALLBACK
608
+ glut_DialsFuncCallback0(int dial, int value) {
609
+ struct callback_args *args = alloc_callback_args();
610
+
611
+ args->arg0.dial = dial;
612
+ args->arg1.value = value;
613
+
614
+ rb_thread_call_with_gvl((gvl_call)glut_DialsFuncCallback, args);
615
+
616
+ free(args);
617
+ }
618
+
619
+ static void *
620
+ glut_TabletMotionFuncCallback(struct callback_args *args) {
621
+ VALUE func = rb_ary_entry(TabletMotionFunc, glutGetWindow());
622
+ VALUE x = INT2NUM(args->arg0.x);
623
+ VALUE y = INT2NUM(args->arg1.y);
624
+
625
+ if (!NIL_P(func))
626
+ rb_funcall(func, call_id, 2, x, y);
627
+
628
+ return NULL;
629
+ }
630
+
631
+ static void GLUTCALLBACK
632
+ glut_TabletMotionFuncCallback0(int x, int y) {
633
+ struct callback_args *args = alloc_callback_args();
634
+
635
+ args->arg0.x = x;
636
+ args->arg1.y = y;
637
+
638
+ rb_thread_call_with_gvl((gvl_call)glut_TabletMotionFuncCallback, args);
639
+
640
+ free(args);
641
+ }
642
+
643
+ static void *
644
+ glut_TabletButtonFuncCallback(struct callback_args *args) {
645
+ VALUE func = rb_ary_entry(TabletButtonFunc, glutGetWindow());
646
+ VALUE button = INT2NUM(args->arg0.button);
647
+ VALUE state = INT2NUM(args->arg1.state);
648
+ VALUE x = INT2NUM(args->arg2.x);
649
+ VALUE y = INT2NUM(args->arg3.y);
650
+
651
+ if (!NIL_P(func))
652
+ rb_funcall(func, call_id, 4, button, state, x, y);
653
+
654
+ return NULL;
655
+ }
656
+
657
+ static void GLUTCALLBACK
658
+ glut_TabletButtonFuncCallback0(int button, int state, int x, int y) {
659
+ struct callback_args *args = alloc_callback_args();
660
+
661
+ args->arg0.button = button;
662
+ args->arg1.state = state;
663
+ args->arg2.x = x;
664
+ args->arg3.y = y;
665
+
666
+ rb_thread_call_with_gvl((gvl_call)glut_TabletButtonFuncCallback, args);
667
+
668
+ free(args);
669
+ }
670
+
671
+ static void *
672
+ glut_OverlayDisplayFuncCallback(void) {
673
+ VALUE func = rb_ary_entry(OverlayDisplayFunc, glutGetWindow());
674
+
675
+ if (!NIL_P(func))
676
+ rb_funcall(func, call_id, 0);
677
+
678
+ return NULL;
679
+ }
680
+
681
+ static void GLUTCALLBACK
682
+ glut_OverlayDisplayFuncCallback0(void) {
683
+ rb_thread_call_with_gvl((gvl_call)glut_OverlayDisplayFuncCallback, NULL);
684
+ }
685
+
686
+ static void *
687
+ glut_WindowStatusFuncCallback(struct callback_args *args) {
688
+ VALUE func = rb_ary_entry(WindowStatusFunc, glutGetWindow());
689
+ VALUE state = INT2NUM(args->arg0.state);
690
+
691
+ if (!NIL_P(func))
692
+ rb_funcall(func, call_id, 1, state);
693
+
694
+ return NULL;
695
+ }
696
+
697
+ static void GLUTCALLBACK
698
+ glut_WindowStatusFuncCallback0(int state) {
699
+ struct callback_args *args = alloc_callback_args();
700
+
701
+ args->arg0.state = state;
702
+
703
+ rb_thread_call_with_gvl((gvl_call)glut_WindowStatusFuncCallback, args);
704
+
705
+ free(args);
706
+ }
707
+
708
+ static void *
709
+ glut_JoystickFuncCallback(struct callback_args *args) {
710
+ VALUE func = rb_ary_entry(joystick_func, glutGetWindow());
711
+ VALUE button_mask = UINT2NUM(args->arg0.button_mask);
712
+ VALUE x = INT2NUM(args->arg1.x);
713
+ VALUE y = INT2NUM(args->arg2.y);
714
+ VALUE z = INT2NUM(args->arg3.z);
715
+
716
+ if (!NIL_P(func))
717
+ rb_funcall(func, call_id, 4, button_mask, x, y, z);
718
+
719
+ return NULL;
720
+ }
721
+
722
+ static void GLUTCALLBACK
723
+ glut_JoystickFuncCallback0(unsigned int button_mask, int x, int y, int z) {
724
+ struct callback_args *args = alloc_callback_args();
725
+
726
+ args->arg0.button_mask = button_mask;
727
+ args->arg1.x = x;
728
+ args->arg2.y = y;
729
+ args->arg3.z = z;
730
+
731
+ rb_thread_call_with_gvl((gvl_call)glut_JoystickFuncCallback, args);
732
+
733
+ free(args);
734
+ }
735
+
736
+ static VALUE
737
+ glut_JoystickFunc(VALUE self, VALUE callback, VALUE _poll_interval) {
738
+ int win = glutGetWindow();
739
+ int poll_interval = NUM2INT(_poll_interval);
740
+
741
+ if (win == 0)
742
+ rb_raise(rb_eRuntimeError, "glutJoystickFunc needs current window");
743
+
744
+ callback = rb_glut_check_callback(self, callback);
745
+
746
+ rb_ary_store(joystick_func, win, callback);
747
+
748
+ if (NIL_P(callback))
749
+ glutJoystickFunc(NULL, -1);
750
+ else
751
+ glutJoystickFunc(glut_JoystickFuncCallback0, poll_interval);
752
+
753
+ return Qnil;
754
+ }
755
+
756
+ static VALUE
757
+ glut_IdleFunc(VALUE self, VALUE callback) {
758
+ callback = rb_glut_check_callback(self, callback);
759
+
760
+ idle_func = callback;
761
+
762
+ if (NIL_P(callback))
763
+ glutIdleFunc(NULL);
764
+ else
765
+ glutIdleFunc(glut_IdleFuncCallback0);
766
+
767
+ return Qnil;
768
+ }
769
+
770
+ static VALUE
771
+ glut_MenuStateFunc(VALUE self, VALUE callback) {
772
+ menustate_func = rb_glut_check_callback(self, callback);
773
+
774
+ if (NIL_P(menustate_func))
775
+ glutMenuStateFunc(NULL);
776
+ else
777
+ glutMenuStateFunc(glut_MenuStateFuncCallback0);
778
+
779
+ return Qnil;
780
+ }
781
+
782
+ static VALUE
783
+ glut_MenuStatusFunc(VALUE self, VALUE callback) {
784
+ menustatus_func = rb_glut_check_callback(self, callback);
785
+
786
+ if (NIL_P(menustatus_func))
787
+ glutMenuStatusFunc(NULL);
788
+ else
789
+ glutMenuStatusFunc(glut_MenuStatusFuncCallback0);
790
+
791
+ return Qnil;
792
+ }
793
+
794
+ static VALUE
795
+ glut_TimerFunc(VALUE self, VALUE _msec, VALUE callback, VALUE _value) {
796
+ unsigned int msec = NUM2UINT(_msec);
797
+ int value = NUM2INT(_value);
798
+
799
+ timer_func = rb_glut_check_callback(self, callback);
800
+
801
+ glutTimerFunc(msec, glut_TimerFuncCallback0, value);
802
+
803
+ return Qnil;
804
+ }
805
+
806
+ void Init_glut_callbacks() {
807
+ VALUE mGlut = rb_path2class("Glut");
808
+
809
+ call_id = rb_intern("call");
810
+ joystick_func = rb_ary_new();
811
+
812
+ rb_global_variable(&joystick_func);
813
+ rb_gc_register_address(&idle_func);
814
+ rb_gc_register_address(&timer_func);
815
+ rb_gc_register_address(&menustate_func);
816
+
817
+ rb_define_module_function(mGlut, "glutJoystickFunc", glut_JoystickFunc, 2);
818
+ rb_define_module_function(mGlut, "glutForceJoystickFunc", glut_ForceJoystickFunc, 0);
819
+ rb_define_module_function(mGlut, "glutIdleFunc", glut_IdleFunc, 1);
820
+ rb_define_module_function(mGlut, "glutMenuStateFunc", glut_MenuStateFunc, 1);
821
+ rb_define_module_function(mGlut, "glutMenuStatusFunc", glut_MenuStatusFunc, 1);
822
+ rb_define_module_function(mGlut, "glutTimerFunc", glut_TimerFunc, 3);
823
+
824
+ WINDOW_CALLBACK_DEFINE(mGlut, ButtonBoxFunc);
825
+ WINDOW_CALLBACK_DEFINE(mGlut, DialsFunc);
826
+ WINDOW_CALLBACK_DEFINE(mGlut, DisplayFunc);
827
+ WINDOW_CALLBACK_DEFINE(mGlut, EntryFunc);
828
+ WINDOW_CALLBACK_DEFINE(mGlut, KeyboardFunc);
829
+ WINDOW_CALLBACK_DEFINE(mGlut, KeyboardUpFunc);
830
+ WINDOW_CALLBACK_DEFINE(mGlut, MotionFunc);
831
+ WINDOW_CALLBACK_DEFINE(mGlut, MouseFunc);
832
+ WINDOW_CALLBACK_DEFINE(mGlut, OverlayDisplayFunc);
833
+ WINDOW_CALLBACK_DEFINE(mGlut, PassiveMotionFunc);
834
+ WINDOW_CALLBACK_DEFINE(mGlut, ReshapeFunc);
835
+ WINDOW_CALLBACK_DEFINE(mGlut, SpaceballButtonFunc);
836
+ WINDOW_CALLBACK_DEFINE(mGlut, SpaceballMotionFunc);
837
+ WINDOW_CALLBACK_DEFINE(mGlut, SpaceballRotateFunc);
838
+ WINDOW_CALLBACK_DEFINE(mGlut, SpecialFunc);
839
+ WINDOW_CALLBACK_DEFINE(mGlut, SpecialUpFunc);
840
+ WINDOW_CALLBACK_DEFINE(mGlut, TabletButtonFunc);
841
+ WINDOW_CALLBACK_DEFINE(mGlut, TabletMotionFunc);
842
+ WINDOW_CALLBACK_DEFINE(mGlut, VisibilityFunc);
843
+ WINDOW_CALLBACK_DEFINE(mGlut, WindowStatusFunc);
844
+ }
845
+