glib2 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. data/ChangeLog +3023 -0
  2. data/README +28 -0
  3. data/Rakefile +87 -0
  4. data/extconf.rb +61 -0
  5. data/sample/bookmarkfile.rb +66 -0
  6. data/sample/completion.rb +45 -0
  7. data/sample/idle.rb +41 -0
  8. data/sample/iochannel.rb +44 -0
  9. data/sample/keyfile.rb +62 -0
  10. data/sample/shell.rb +36 -0
  11. data/sample/spawn.rb +25 -0
  12. data/sample/timeout.rb +28 -0
  13. data/sample/timeout2.rb +35 -0
  14. data/sample/timer.rb +40 -0
  15. data/sample/type-register.rb +103 -0
  16. data/sample/type-register2.rb +104 -0
  17. data/sample/utils.rb +54 -0
  18. data/src/glib-enum-types.c +1032 -0
  19. data/src/glib-enum-types.h +140 -0
  20. data/src/lib/glib-mkenums.rb +199 -0
  21. data/src/lib/glib2.rb +220 -0
  22. data/src/lib/mkmf-gnome2.rb +390 -0
  23. data/src/lib/pkg-config.rb +137 -0
  24. data/src/rbgcompat.h +30 -0
  25. data/src/rbglib.c +320 -0
  26. data/src/rbglib.h +96 -0
  27. data/src/rbglib_bookmarkfile.c +595 -0
  28. data/src/rbglib_completion.c +192 -0
  29. data/src/rbglib_convert.c +195 -0
  30. data/src/rbglib_error.c +95 -0
  31. data/src/rbglib_fileutils.c +83 -0
  32. data/src/rbglib_i18n.c +44 -0
  33. data/src/rbglib_int64.c +157 -0
  34. data/src/rbglib_iochannel.c +883 -0
  35. data/src/rbglib_keyfile.c +846 -0
  36. data/src/rbglib_maincontext.c +917 -0
  37. data/src/rbglib_mainloop.c +87 -0
  38. data/src/rbglib_messages.c +150 -0
  39. data/src/rbglib_pollfd.c +111 -0
  40. data/src/rbglib_shell.c +68 -0
  41. data/src/rbglib_source.c +190 -0
  42. data/src/rbglib_spawn.c +345 -0
  43. data/src/rbglib_threads.c +51 -0
  44. data/src/rbglib_timer.c +127 -0
  45. data/src/rbglib_unicode.c +611 -0
  46. data/src/rbglib_utils.c +386 -0
  47. data/src/rbglib_win32.c +136 -0
  48. data/src/rbgobj_boxed.c +251 -0
  49. data/src/rbgobj_closure.c +337 -0
  50. data/src/rbgobj_convert.c +167 -0
  51. data/src/rbgobj_enums.c +961 -0
  52. data/src/rbgobj_fundamental.c +30 -0
  53. data/src/rbgobj_object.c +892 -0
  54. data/src/rbgobj_param.c +390 -0
  55. data/src/rbgobj_paramspecs.c +305 -0
  56. data/src/rbgobj_signal.c +963 -0
  57. data/src/rbgobj_strv.c +61 -0
  58. data/src/rbgobj_type.c +851 -0
  59. data/src/rbgobj_typeinstance.c +121 -0
  60. data/src/rbgobj_typeinterface.c +148 -0
  61. data/src/rbgobj_typemodule.c +66 -0
  62. data/src/rbgobj_typeplugin.c +49 -0
  63. data/src/rbgobj_value.c +313 -0
  64. data/src/rbgobj_valuearray.c +59 -0
  65. data/src/rbgobj_valuetypes.c +298 -0
  66. data/src/rbgobject.c +406 -0
  67. data/src/rbgobject.h +265 -0
  68. data/src/rbgprivate.h +88 -0
  69. data/src/rbgutil.c +222 -0
  70. data/src/rbgutil.h +82 -0
  71. data/src/rbgutil_callback.c +231 -0
  72. data/test/glib-test-init.rb +6 -0
  73. data/test/glib-test-utils.rb +12 -0
  74. data/test/run-test.rb +25 -0
  75. data/test/test_enum.rb +99 -0
  76. data/test/test_file_utils.rb +15 -0
  77. data/test/test_glib2.rb +120 -0
  78. data/test/test_iochannel.rb +275 -0
  79. data/test/test_key_file.rb +38 -0
  80. data/test/test_mkenums.rb +25 -0
  81. data/test/test_signal.rb +20 -0
  82. data/test/test_timeout.rb +28 -0
  83. data/test/test_unicode.rb +369 -0
  84. data/test/test_utils.rb +37 -0
  85. data/test/test_win32.rb +13 -0
  86. metadata +165 -0
@@ -0,0 +1,963 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
+ /**********************************************************************
3
+
4
+ rbgobj_signal.c -
5
+
6
+ $Author: ssimons $
7
+ $Date: 2007/07/25 17:04:28 $
8
+ created at: Sat Jul 27 16:56:01 JST 2002
9
+
10
+ Copyright (C) 2002-2004 Ruby-GNOME2 Project Team
11
+ Copyright (C) 2002,2003 Masahiro Sakai
12
+
13
+ **********************************************************************/
14
+
15
+ #include "rbgprivate.h"
16
+
17
+ static VALUE cSignal;
18
+ VALUE rbgobj_signal_wrap(guint sig_id);
19
+
20
+ #define default_handler_method_prefix "signal_do_"
21
+
22
+ /**********************************************************************/
23
+
24
+ static VALUE signal_func_table;
25
+
26
+ void
27
+ rbgobj_set_signal_func(klass, sig_name, func)
28
+ VALUE klass;
29
+ gchar* sig_name;
30
+ GValToRValSignalFunc func;
31
+ {
32
+ VALUE obj = Data_Wrap_Struct(rb_cData, NULL, NULL, func);
33
+ guint signal_id = g_signal_lookup(sig_name, CLASS2GTYPE(klass));
34
+ rb_hash_aset(signal_func_table, UINT2NUM(signal_id), obj);
35
+ }
36
+
37
+ GValToRValSignalFunc
38
+ rbgobj_get_signal_func(guint signal_id)
39
+ {
40
+ GValToRValSignalFunc func = NULL;
41
+ VALUE func_obj = rb_hash_aref(signal_func_table, UINT2NUM(signal_id));
42
+ if (!NIL_P(func_obj))
43
+ Data_Get_Struct(func_obj, void, func);
44
+ return func;
45
+ }
46
+
47
+ /**********************************************************************/
48
+
49
+ static VALUE eNoSignalError;
50
+
51
+ // FIXME: use rb_protect
52
+ static gboolean
53
+ accumulator_func(GSignalInvocationHint* ihint,
54
+ GValue* return_accu,
55
+ const GValue* handler_return,
56
+ gpointer data)
57
+ {
58
+ VALUE proc = (VALUE)data;
59
+ VALUE val = GVAL2RVAL(return_accu);
60
+ VALUE new = GVAL2RVAL(handler_return);
61
+ VALUE hint = Qnil; // FIXME
62
+ VALUE tmp;
63
+ gboolean continue_emission = TRUE;
64
+
65
+ tmp = rb_funcall(proc, rb_intern("call"), 3, hint, val, new);
66
+ /* FIXME */
67
+ if (TYPE(tmp) == T_ARRAY) {
68
+ continue_emission = RVAL2CBOOL(rb_ary_entry(tmp, 0));
69
+ val = rb_ary_entry(tmp, 1);
70
+ } else {
71
+ val = tmp;
72
+ }
73
+ rbgobj_rvalue_to_gvalue(val, return_accu);
74
+
75
+ return continue_emission;
76
+ }
77
+
78
+ static VALUE
79
+ gobj_s_signal_new(int argc, VALUE* argv, VALUE self)
80
+ {
81
+ const RGObjClassInfo* cinfo = rbgobj_lookup_class(self);
82
+ VALUE signal_name, signal_flags, accumulator, return_type, params;
83
+ GClosure* class_closure;
84
+ GType* param_types;
85
+ guint n_params;
86
+ int i;
87
+ guint sig;
88
+
89
+ rb_scan_args(argc, argv, "4*", &signal_name, &signal_flags,
90
+ &accumulator, &return_type, &params);
91
+
92
+ if (cinfo->klass != self)
93
+ rb_raise(rb_eTypeError, "%s isn't registerd class",
94
+ rb_class2name(self));
95
+
96
+ if (SYMBOL_P(signal_name))
97
+ signal_name = rb_str_new2(rb_id2name(SYM2ID(signal_name)));
98
+ else
99
+ StringValue(signal_name);
100
+
101
+ {
102
+ VALUE factory;
103
+ VALUE proc;
104
+ ID method_id;
105
+
106
+ method_id = rb_to_id(rb_str_concat(rb_str_new2(default_handler_method_prefix), signal_name));
107
+
108
+ factory = rb_eval_string(
109
+ "lambda{|klass, id|\n"
110
+ " lambda{|instance,*args|\n"
111
+ " klass.instance_method(id).bind(instance).call(*args)\n"
112
+ " }\n"
113
+ "}\n");
114
+ proc = rb_funcall(factory, rb_intern("call"), 2, self, ID2SYM(method_id));
115
+
116
+ class_closure = g_rclosure_new(proc, Qnil, NULL);
117
+ g_rclosure_attach(class_closure, self);
118
+ }
119
+
120
+ if (NIL_P(params)) {
121
+ n_params = 0;
122
+ param_types = NULL;
123
+ } else {
124
+ n_params = RARRAY_LEN(params);
125
+ param_types = ALLOCA_N(GType, n_params);
126
+ for (i = 0; i < n_params; i++)
127
+ param_types[i] = rbgobj_gtype_get(RARRAY_PTR(params)[i]);
128
+ }
129
+
130
+ sig = g_signal_newv(StringValuePtr(signal_name),
131
+ cinfo->gtype,
132
+ NUM2INT(signal_flags),
133
+ class_closure,
134
+ NIL_P(accumulator) ? NULL : accumulator_func,
135
+ NIL_P(accumulator) ? NULL : (gpointer)accumulator,
136
+ NULL, /* c_marshaller */
137
+ rbgobj_gtype_get(return_type),
138
+ n_params,
139
+ param_types);
140
+
141
+ if (!sig)
142
+ rb_raise(rb_eRuntimeError, "g_signal_newv failed");
143
+
144
+ if (!NIL_P(accumulator))
145
+ G_RELATIVE(self, accumulator); /* FIXME */
146
+
147
+ return rbgobj_signal_wrap(sig);
148
+ }
149
+
150
+ static void
151
+ _signal_list(VALUE result, GType gtype)
152
+ {
153
+ guint n_ids, i;
154
+ guint* ids = g_signal_list_ids(gtype, &n_ids);
155
+ for (i = 0; i < n_ids; i++)
156
+ rb_ary_push(result, rb_str_new2(g_signal_name(ids[i])));
157
+ g_free(ids);
158
+ }
159
+
160
+ static VALUE
161
+ gobj_s_signals(int argc, VALUE* argv, VALUE self)
162
+ {
163
+ GType gtype;
164
+ VALUE inherited_too, result;
165
+
166
+ if (rb_scan_args(argc, argv, "01", &inherited_too) == 0)
167
+ inherited_too = Qtrue;
168
+ gtype = CLASS2GTYPE(self);
169
+ result = rb_ary_new();
170
+
171
+ if (RVAL2CBOOL(inherited_too)){
172
+ guint n_interfaces, i;
173
+ GType* interfaces = g_type_interfaces(gtype, &n_interfaces);
174
+ for (i = 0; i < n_interfaces; i++)
175
+ _signal_list(result, interfaces[i]);
176
+ g_free(interfaces);
177
+
178
+ for (; gtype; gtype = g_type_parent(gtype))
179
+ _signal_list(result, gtype);
180
+ } else if (GTYPE2CLASS(gtype) == self) {
181
+ _signal_list(result, gtype);
182
+ }
183
+
184
+ return result;
185
+ }
186
+
187
+ static VALUE
188
+ gobj_s_signal(VALUE self, VALUE name)
189
+ {
190
+ const char* sig_name;
191
+ guint sig_id;
192
+
193
+ if (SYMBOL_P(name))
194
+ sig_name = rb_id2name(SYM2ID(name));
195
+ else
196
+ sig_name = StringValuePtr(name);
197
+
198
+ sig_id = g_signal_lookup(sig_name, CLASS2GTYPE(self));
199
+ if (!sig_id)
200
+ rb_raise(eNoSignalError, "no such signal: %s", sig_name);
201
+
202
+ return rbgobj_signal_wrap(sig_id);
203
+ }
204
+
205
+ static VALUE
206
+ gobj_sig_has_handler_pending(argc, argv, self)
207
+ int argc;
208
+ VALUE *argv;
209
+ VALUE self;
210
+ {
211
+ VALUE sig, may_be_blocked;
212
+ const char* sig_name;
213
+ guint signal_id;
214
+ GQuark detail;
215
+
216
+ rb_scan_args(argc, argv, "11", &sig, &may_be_blocked);
217
+
218
+ if (SYMBOL_P(sig))
219
+ sig_name = rb_id2name(SYM2ID(sig));
220
+ else
221
+ sig_name = StringValuePtr(sig);
222
+
223
+ if (!g_signal_parse_name(sig_name, CLASS2GTYPE(CLASS_OF(self)), &signal_id, &detail, TRUE))
224
+ rb_raise(eNoSignalError, "no such signal: %s", sig_name);
225
+
226
+ return CBOOL2RVAL(g_signal_has_handler_pending(RVAL2GOBJ(self),
227
+ signal_id, detail,
228
+ RVAL2CBOOL(may_be_blocked)));
229
+ }
230
+
231
+ static VALUE
232
+ gobj_sig_connect_impl(after, argc, argv, self)
233
+ gboolean after;
234
+ int argc;
235
+ VALUE *argv;
236
+ VALUE self;
237
+ {
238
+ VALUE sig, rest;
239
+ int i;
240
+ GClosure* rclosure;
241
+ const char* sig_name;
242
+ guint signal_id;
243
+ GQuark detail;
244
+ VALUE func;
245
+ GObject *g_object;
246
+ gchar *tag;
247
+
248
+ rb_scan_args(argc, argv, "1*", &sig, &rest);
249
+
250
+ if (NIL_P(rest)) rest = rb_ary_new();
251
+
252
+ if (SYMBOL_P(sig))
253
+ sig_name = rb_id2name(SYM2ID(sig));
254
+ else
255
+ sig_name = StringValuePtr(sig);
256
+
257
+ if (!g_signal_parse_name(sig_name, CLASS2GTYPE(CLASS_OF(self)), &signal_id, &detail, TRUE))
258
+ rb_raise(eNoSignalError, "no such signal: %s", sig_name);
259
+
260
+ func = rb_block_proc();
261
+ rclosure = g_rclosure_new(func, rest,
262
+ rbgobj_get_signal_func(signal_id));
263
+ g_rclosure_attach((GClosure *)rclosure, self);
264
+ g_object = RVAL2GOBJ(self);
265
+ tag = g_strdup_printf("%s::%s",
266
+ G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(g_object)),
267
+ sig_name);
268
+ g_rclosure_set_tag((GClosure *)rclosure, tag);
269
+ g_free(tag);
270
+ i = g_signal_connect_closure_by_id(g_object, signal_id, detail, rclosure, after);
271
+
272
+ return INT2FIX(i);
273
+ }
274
+
275
+ static VALUE
276
+ gobj_sig_connect(argc, argv, self)
277
+ int argc;
278
+ VALUE *argv;
279
+ VALUE self;
280
+ {
281
+ return gobj_sig_connect_impl(FALSE, argc, argv, self);
282
+ }
283
+
284
+ static VALUE
285
+ gobj_sig_connect_after(argc, argv, self)
286
+ int argc;
287
+ VALUE *argv;
288
+ VALUE self;
289
+ {
290
+ return gobj_sig_connect_impl(TRUE, argc, argv, self);
291
+ }
292
+
293
+ #if 0
294
+ static VALUE
295
+ gobj_sig_get_invocation_hint(self)
296
+ VALUE self;
297
+ {
298
+ GSignalInvocationHint* hint;
299
+ hint = g_signal_get_invocation_hint(RVAL2GOBJ(self));
300
+ return rb_ary_new3(3,
301
+ rbgobj_signal_wrap(hint->signal_id),
302
+ hint->detail ? rb_str_new2(g_quark_to_string(hint->detail)) : Qnil,
303
+ INT2NUM(hint->run_type));
304
+ }
305
+ #endif
306
+
307
+ struct emit_arg{
308
+ VALUE self;
309
+ VALUE args;
310
+
311
+ GSignalQuery query;
312
+ GQuark detail;
313
+ GValueArray* instance_and_params;
314
+ };
315
+
316
+ static VALUE
317
+ emit_body(struct emit_arg* arg)
318
+ {
319
+ GValue param = { 0, };
320
+
321
+ g_value_init(&param, G_TYPE_FROM_INSTANCE(RVAL2GOBJ(arg->self)));
322
+ rbgobj_rvalue_to_gvalue(arg->self, &param);
323
+ g_value_array_append(arg->instance_and_params, &param);
324
+ g_value_unset(&param);
325
+
326
+ {
327
+ int i;
328
+ for (i = 0; i < arg->query.n_params; i++){
329
+ GType gtype = arg->query.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
330
+
331
+ g_value_init(&param, gtype);
332
+
333
+ rbgobj_rvalue_to_gvalue(rb_ary_entry(arg->args, i), &param);
334
+ g_value_array_append(arg->instance_and_params, &param);
335
+ g_value_unset(&param);
336
+ }
337
+ }
338
+
339
+ {
340
+ gboolean use_ret = (arg->query.return_type != G_TYPE_NONE);
341
+ GValue return_value = {0,};
342
+
343
+ if (use_ret)
344
+ g_value_init(&return_value,
345
+ arg->query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
346
+
347
+ g_signal_emitv(arg->instance_and_params->values,
348
+ arg->query.signal_id, arg->detail,
349
+ (use_ret) ? &return_value : NULL);
350
+
351
+ if (use_ret) {
352
+ VALUE ret = GVAL2RVAL(&return_value);
353
+ g_value_unset(&return_value);
354
+ return ret;
355
+ } else {
356
+ return Qnil;
357
+ }
358
+ }
359
+ }
360
+
361
+ static VALUE
362
+ emit_ensure(struct emit_arg* arg)
363
+ {
364
+ g_value_array_free(arg->instance_and_params);
365
+ return Qnil;
366
+ }
367
+
368
+ static VALUE
369
+ gobj_sig_emit(argc, argv, self)
370
+ int argc;
371
+ VALUE *argv;
372
+ VALUE self;
373
+ {
374
+ VALUE sig;
375
+ const char* sig_name;
376
+ guint signal_id;
377
+ struct emit_arg arg;
378
+
379
+ rb_scan_args(argc, argv, "1*", &sig, &arg.args);
380
+
381
+ if (SYMBOL_P(sig))
382
+ sig_name = rb_id2name(SYM2ID(sig));
383
+ else
384
+ sig_name = StringValuePtr(sig);
385
+
386
+ if (!g_signal_parse_name(sig_name,
387
+ CLASS2GTYPE(CLASS_OF(self)),
388
+ &signal_id, &arg.detail, FALSE))
389
+ rb_raise(eNoSignalError, "invalid signal \"%s\"", sig_name);
390
+
391
+ g_signal_query(signal_id, &arg.query);
392
+
393
+ if (arg.query.n_params != RARRAY_LEN(arg.args))
394
+ rb_raise(rb_eArgError, "wrong number of arguments(%ld for %d)",
395
+ RARRAY_LEN(arg.args) + 1,
396
+ arg.query.n_params + 1);
397
+
398
+ arg.self = self;
399
+ arg.instance_and_params = g_value_array_new(1 + arg.query.n_params);
400
+
401
+ return rb_ensure(emit_body, (VALUE)&arg, emit_ensure, (VALUE)&arg);
402
+ }
403
+
404
+ static VALUE
405
+ gobj_sig_emit_stop(self, sig)
406
+ VALUE self, sig;
407
+ {
408
+ gpointer instance = RVAL2GOBJ(self);
409
+ const char* sig_name;
410
+ guint signal_id;
411
+ GQuark detail;
412
+
413
+ if (SYMBOL_P(sig))
414
+ sig_name = rb_id2name(SYM2ID(sig));
415
+ else
416
+ sig_name = StringValuePtr(sig);
417
+
418
+ if (!g_signal_parse_name(sig_name,
419
+ CLASS2GTYPE(CLASS_OF(self)),
420
+ &signal_id, &detail, FALSE))
421
+ rb_raise(eNoSignalError, "invalid signal \"%s\"", sig_name);
422
+
423
+ g_signal_stop_emission(instance, signal_id, detail);
424
+ return self;
425
+ }
426
+
427
+ static VALUE gobj_sig_handler_unblock(VALUE self, VALUE id);
428
+
429
+ static VALUE
430
+ _sig_handler_block_ensure(arg)
431
+ VALUE arg;
432
+ {
433
+ VALUE self = RARRAY_PTR(arg)[0];
434
+ VALUE id = RARRAY_PTR(arg)[1];
435
+ gobj_sig_handler_unblock(self, id);
436
+ return Qnil;
437
+ }
438
+
439
+ static VALUE
440
+ gobj_sig_handler_block(self, id)
441
+ VALUE self, id;
442
+ {
443
+ g_signal_handler_block(RVAL2GOBJ(self), NUM2ULONG(id));
444
+ if (rb_block_given_p())
445
+ rb_ensure(rb_yield, self, _sig_handler_block_ensure,
446
+ rb_ary_new3(2, self, id));
447
+ return self;
448
+ }
449
+
450
+ static VALUE
451
+ gobj_sig_handler_unblock(self, id)
452
+ VALUE self, id;
453
+ {
454
+ g_signal_handler_unblock(RVAL2GOBJ(self), NUM2ULONG(id));
455
+ return self;
456
+ }
457
+
458
+ static VALUE
459
+ gobj_sig_handler_disconnect(self, id)
460
+ VALUE self, id;
461
+ {
462
+ g_signal_handler_disconnect(RVAL2GOBJ(self), NUM2ULONG(id));
463
+ return self;
464
+ }
465
+
466
+ static VALUE
467
+ gobj_sig_handler_is_connected(self, id)
468
+ VALUE self, id;
469
+ {
470
+ return CBOOL2RVAL(g_signal_handler_is_connected(RVAL2GOBJ(self), NUM2ULONG(id)));
471
+ }
472
+
473
+ #if 0
474
+ gulong g_signal_handler_find (gpointer instance,
475
+ GSignalMatchType mask,
476
+ guint signal_id,
477
+ GQuark detail,
478
+ GClosure *closure,
479
+ gpointer func,
480
+ gpointer data);
481
+ guint g_signal_handlers_block_matched (gpointer instance,
482
+ GSignalMatchType mask,
483
+ guint signal_id,
484
+ GQuark detail,
485
+ GClosure *closure,
486
+ gpointer func,
487
+ gpointer data);
488
+ guint g_signal_handlers_unblock_matched (gpointer instance,
489
+ GSignalMatchType mask,
490
+ guint signal_id,
491
+ GQuark detail,
492
+ GClosure *closure,
493
+ gpointer func,
494
+ gpointer data);
495
+ guint g_signal_handlers_disconnect_matched (gpointer instance,
496
+ GSignalMatchType mask,
497
+ guint signal_id,
498
+ GQuark detail,
499
+ GClosure *closure,
500
+ gpointer func,
501
+ gpointer data);
502
+ #endif
503
+
504
+ static VALUE
505
+ chain_from_overridden_body(struct emit_arg* arg)
506
+ {
507
+ g_value_init(arg->instance_and_params->values,
508
+ G_TYPE_FROM_INSTANCE(RVAL2GOBJ(arg->self)));
509
+ rbgobj_rvalue_to_gvalue(arg->self, arg->instance_and_params->values);
510
+
511
+ {
512
+ GValue* params = arg->instance_and_params->values + 1;
513
+ int i;
514
+ for (i = 0; i < arg->query.n_params; i++) {
515
+ GType gtype = arg->query.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
516
+ g_value_init(params + i, gtype);
517
+ rbgobj_rvalue_to_gvalue(rb_ary_entry(arg->args, i), params + i);
518
+ }
519
+ }
520
+
521
+ {
522
+ gboolean use_ret = (arg->query.return_type != G_TYPE_NONE);
523
+ GValue return_value = {0,};
524
+
525
+ if (use_ret)
526
+ g_value_init(&return_value,
527
+ arg->query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
528
+
529
+ g_signal_chain_from_overridden(arg->instance_and_params->values,
530
+ (use_ret) ? &return_value : NULL);
531
+
532
+ if (use_ret) {
533
+ VALUE ret = GVAL2RVAL(&return_value);
534
+ g_value_unset(&return_value);
535
+ return ret;
536
+ } else {
537
+ return Qnil;
538
+ }
539
+ }
540
+ }
541
+
542
+ static VALUE
543
+ gobj_sig_chain_from_overridden(argc, argv, self)
544
+ int argc;
545
+ VALUE* argv;
546
+ VALUE self;
547
+ {
548
+ struct emit_arg arg;
549
+
550
+ {
551
+ GSignalInvocationHint* hint;
552
+ hint = g_signal_get_invocation_hint(RVAL2GOBJ(self));
553
+ if (!hint)
554
+ rb_raise(rb_eRuntimeError, "can't get signal invocation hint");
555
+ g_signal_query(hint->signal_id, &arg.query);
556
+ }
557
+
558
+ if (arg.query.n_params != argc)
559
+ rb_raise(rb_eArgError, "wrong number of arguments(%d for %d)",
560
+ argc, arg.query.n_params);
561
+
562
+ arg.self = self;
563
+ arg.args = rb_ary_new4(argc, argv);
564
+ arg.instance_and_params = g_value_array_new(1 + argc);
565
+
566
+ return rb_ensure(chain_from_overridden_body, (VALUE)&arg,
567
+ emit_ensure, (VALUE)&arg);
568
+ }
569
+
570
+ static VALUE
571
+ gobj_s_method_added(klass, id)
572
+ VALUE klass, id;
573
+ {
574
+ const RGObjClassInfo* cinfo = rbgobj_lookup_class(klass);
575
+ const char* name = rb_id2name(SYM2ID(id));
576
+ const int prefix_len = strlen(default_handler_method_prefix);
577
+ guint signal_id;
578
+
579
+ if (cinfo->klass != klass) return Qnil;
580
+ if (strncmp(default_handler_method_prefix, name, prefix_len)) return Qnil;
581
+
582
+ signal_id = g_signal_lookup(name + prefix_len, cinfo->gtype);
583
+ if (!signal_id) return Qnil;
584
+
585
+ {
586
+ GSignalQuery query;
587
+ g_signal_query(signal_id, &query);
588
+ if (query.itype == cinfo->gtype)
589
+ return Qnil;
590
+ }
591
+
592
+ {
593
+ VALUE f = rb_eval_string(
594
+ "lambda{|klass, id|\n"
595
+ " lambda{|instance,*args|\n"
596
+ " klass.instance_method(id).bind(instance).call(*args)\n"
597
+ " }\n"
598
+ "}\n");
599
+ VALUE proc = rb_funcall(f, rb_intern("call"), 2, klass, id);
600
+ GClosure* rclosure = g_rclosure_new(proc, Qnil,
601
+ rbgobj_get_signal_func(signal_id));
602
+ g_rclosure_attach((GClosure *)rclosure, klass);
603
+ g_signal_override_class_closure(signal_id, cinfo->gtype, rclosure);
604
+ }
605
+
606
+ {
607
+ VALUE mod = rb_define_module_under(klass, RubyGObjectHookModule);
608
+ rb_include_module(klass, mod);
609
+ rb_define_method(mod, name, gobj_sig_chain_from_overridden, -1);
610
+ }
611
+
612
+ return Qnil;
613
+ }
614
+
615
+ static void
616
+ Init_signal_misc()
617
+ {
618
+ signal_func_table = rb_hash_new();
619
+ rb_global_variable(&signal_func_table);
620
+
621
+ rb_define_method(mMetaInterface, "signal_new", gobj_s_signal_new, -1);
622
+ rb_define_method(mMetaInterface, "signals", gobj_s_signals, -1);
623
+ rb_define_method(mMetaInterface, "signal", gobj_s_signal, 1);
624
+
625
+ rb_define_method(cInstantiatable, "signal_has_handler_pending?",
626
+ gobj_sig_has_handler_pending, -1);
627
+ rb_define_method(cInstantiatable, "signal_connect", gobj_sig_connect, -1);
628
+ rb_define_method(cInstantiatable, "signal_connect_after",
629
+ gobj_sig_connect_after, -1);
630
+
631
+ #if 0
632
+ rb_define_method(cInstantiatable, "signal_invocation_hint",
633
+ gobj_sig_get_invocation_hint, 0);
634
+ #endif
635
+
636
+ rb_define_method(cInstantiatable, "signal_emit",
637
+ gobj_sig_emit, -1);
638
+ rb_define_method(cInstantiatable, "signal_emit_stop",
639
+ gobj_sig_emit_stop, 1);
640
+ rb_define_method(cInstantiatable, "signal_handler_block",
641
+ gobj_sig_handler_block, 1);
642
+ rb_define_method(cInstantiatable, "signal_handler_unblock",
643
+ gobj_sig_handler_unblock, 1);
644
+ rb_define_method(cInstantiatable, "signal_handler_disconnect",
645
+ gobj_sig_handler_disconnect, 1);
646
+
647
+ rb_define_method(cInstantiatable, "signal_handler_is_connected?",
648
+ gobj_sig_handler_is_connected, 1);
649
+
650
+ rb_define_singleton_method(cInstantiatable, "method_added",
651
+ gobj_s_method_added, 1);
652
+ }
653
+
654
+ /**********************************************************************/
655
+
656
+ VALUE
657
+ rbgobj_signal_wrap(sig_id)
658
+ guint sig_id;
659
+ {
660
+ VALUE result;
661
+ GSignalQuery* query;
662
+
663
+ result = Data_Make_Struct(cSignal, GSignalQuery, NULL, free, query);
664
+ g_signal_query(sig_id, query);
665
+ return result;
666
+ }
667
+
668
+ static VALUE
669
+ query_signal_id(self)
670
+ VALUE self;
671
+ {
672
+ GSignalQuery* query;
673
+ Data_Get_Struct(self, GSignalQuery, query);
674
+ return UINT2NUM(query->signal_id);
675
+ }
676
+
677
+ static VALUE
678
+ query_signal_name(self)
679
+ VALUE self;
680
+ {
681
+ GSignalQuery* query;
682
+ Data_Get_Struct(self, GSignalQuery, query);
683
+ return rb_str_new2(query->signal_name);
684
+ }
685
+
686
+ static VALUE
687
+ query_itype(self)
688
+ VALUE self;
689
+ {
690
+ GSignalQuery* query;
691
+ Data_Get_Struct(self, GSignalQuery, query);
692
+ return rbgobj_gtype_new(query->itype);
693
+ }
694
+
695
+ static VALUE
696
+ query_owner(self)
697
+ VALUE self;
698
+ {
699
+ GSignalQuery* query;
700
+ Data_Get_Struct(self, GSignalQuery, query);
701
+ return GTYPE2CLASS(query->itype);
702
+ }
703
+
704
+ static VALUE
705
+ query_return_type(self)
706
+ VALUE self;
707
+ {
708
+ GSignalQuery* query;
709
+ Data_Get_Struct(self, GSignalQuery, query);
710
+ return rbgobj_gtype_new(query->return_type);
711
+ }
712
+
713
+ static VALUE
714
+ query_signal_flags(self)
715
+ VALUE self;
716
+ {
717
+ GSignalQuery* query;
718
+ Data_Get_Struct(self, GSignalQuery, query);
719
+ return UINT2NUM(query->signal_flags);
720
+ }
721
+
722
+ static VALUE
723
+ query_param_types(self)
724
+ VALUE self;
725
+ {
726
+ GSignalQuery* query;
727
+ VALUE result;
728
+ int i;
729
+ Data_Get_Struct(self, GSignalQuery, query);
730
+
731
+ result = rb_ary_new2(query->n_params);
732
+ for (i = 0; i < query->n_params; i++)
733
+ rb_ary_store(result, i, rbgobj_gtype_new(query->param_types[i]));
734
+
735
+ return result;
736
+ }
737
+
738
+ static VALUE
739
+ query_inspect(self)
740
+ VALUE self;
741
+ {
742
+ GSignalQuery* query;
743
+ gchar* s;
744
+ VALUE result, v;
745
+
746
+ Data_Get_Struct(self, GSignalQuery, query);
747
+
748
+ v = rb_inspect(GTYPE2CLASS(query->itype));
749
+
750
+ s = g_strdup_printf("#<%s: %s#%s>",
751
+ rb_class2name(CLASS_OF(self)),
752
+ StringValuePtr(v),
753
+ query->signal_name);
754
+ result = rb_str_new2(s);
755
+ g_free(s);
756
+
757
+ return result;
758
+ }
759
+
760
+ #define query_is_flag(flag) \
761
+ static VALUE \
762
+ query_is_##flag(self) \
763
+ VALUE self; \
764
+ { \
765
+ GSignalQuery* query; \
766
+ Data_Get_Struct(self, GSignalQuery, query); \
767
+ return CBOOL2RVAL(query->signal_flags & flag); \
768
+ }
769
+
770
+ query_is_flag(G_SIGNAL_RUN_FIRST)
771
+ query_is_flag(G_SIGNAL_RUN_LAST)
772
+ query_is_flag(G_SIGNAL_RUN_CLEANUP)
773
+ query_is_flag(G_SIGNAL_NO_RECURSE)
774
+ query_is_flag(G_SIGNAL_DETAILED)
775
+ query_is_flag(G_SIGNAL_ACTION)
776
+ query_is_flag(G_SIGNAL_NO_HOOKS)
777
+
778
+
779
+ static gboolean
780
+ hook_func(GSignalInvocationHint* ihint,
781
+ guint n_param_values,
782
+ const GValue* param_values,
783
+ gpointer data)
784
+ {
785
+ GClosure* closure = data;
786
+ GValue ret_val ={0,};
787
+ gboolean ret;
788
+
789
+ g_value_init(&ret_val, G_TYPE_BOOLEAN);
790
+ g_closure_invoke(closure, &ret_val, n_param_values, param_values, ihint);
791
+ ret = g_value_get_boolean(&ret_val);
792
+ g_value_unset(&ret_val);
793
+
794
+ return ret;
795
+ }
796
+
797
+ static gulong
798
+ g_signal_add_emission_hook_closure (guint signal_id,
799
+ GQuark detail,
800
+ GClosure* closure)
801
+ {
802
+ guint hook_id;
803
+ g_closure_ref(closure);
804
+ g_closure_sink(closure);
805
+ hook_id = g_signal_add_emission_hook(signal_id, detail,
806
+ &hook_func, closure,
807
+ (GDestroyNotify)&g_closure_unref);
808
+ return hook_id;
809
+ }
810
+
811
+ static VALUE
812
+ signal_add_emission_hook(int argc, VALUE* argv, VALUE self)
813
+ {
814
+ GSignalQuery* query;
815
+ VALUE proc;
816
+ guint hook_id;
817
+ GQuark detail = 0;
818
+ GClosure* closure;
819
+
820
+ Data_Get_Struct(self, GSignalQuery, query);
821
+
822
+ if (query->signal_flags & G_SIGNAL_DETAILED) {
823
+ VALUE detail_obj;
824
+ if (rb_scan_args(argc, argv, "01&", &detail_obj, &proc) == 1) {
825
+ if (SYMBOL_P(detail_obj))
826
+ detail = g_quark_from_string(rb_id2name(SYM2ID(detail_obj)));
827
+ else
828
+ detail = g_quark_from_string(StringValuePtr(detail_obj));
829
+ }
830
+ } else {
831
+ rb_scan_args(argc, argv, "00&", &proc);
832
+ }
833
+
834
+ closure = g_rclosure_new(proc, Qnil,
835
+ rbgobj_get_signal_func(query->signal_id));
836
+ g_rclosure_attach(closure, self);
837
+ hook_id = g_signal_add_emission_hook_closure(query->signal_id, detail, closure);
838
+ return ULONG2NUM(hook_id);
839
+ }
840
+
841
+ static VALUE
842
+ signal_remove_emission_hook(VALUE self, VALUE hook_id)
843
+ {
844
+ GSignalQuery* query;
845
+ Data_Get_Struct(self, GSignalQuery, query);
846
+ g_signal_remove_emission_hook(query->signal_id, NUM2ULONG(hook_id));
847
+ return Qnil;
848
+ }
849
+
850
+ static void
851
+ Init_signal_class()
852
+ {
853
+ VALUE cSignalFlags, cSignalMatchType;
854
+
855
+ cSignal = rb_define_class_under(mGLib, "Signal", rb_cData);
856
+
857
+ rb_define_method(cSignal, "id", query_signal_id, 0);
858
+ rb_define_method(cSignal, "name", query_signal_name, 0);
859
+ rb_define_method(cSignal, "flags", query_signal_flags, 0);
860
+ rb_define_method(cSignal, "itype", query_itype, 0);
861
+ rb_define_method(cSignal, "owner", query_owner, 0);
862
+ rb_define_method(cSignal, "return_type", query_return_type, 0);
863
+ rb_define_method(cSignal, "param_types", query_param_types, 0);
864
+ rb_define_method(cSignal, "inspect", query_inspect, 0);
865
+
866
+ rb_define_method(cSignal, "add_emission_hook", signal_add_emission_hook, -1);
867
+ rb_define_method(cSignal, "remove_emission_hook", signal_remove_emission_hook, 1);
868
+
869
+ /* GSignalFlags */
870
+ cSignalFlags = G_DEF_CLASS(G_TYPE_SIGNAL_FLAGS, "SignalFlags", mGLib);
871
+ G_DEF_CONSTANTS(cSignal, G_TYPE_SIGNAL_FLAGS, "G_SIGNAL_");
872
+ rb_define_const(cSignalFlags, "MASK", INT2NUM(G_SIGNAL_FLAGS_MASK));
873
+ rb_define_const(cSignal, "FLAGS_MASK", INT2NUM(G_SIGNAL_FLAGS_MASK));
874
+
875
+ rb_define_method(cSignal, "run_first?", query_is_G_SIGNAL_RUN_FIRST, 0);
876
+ rb_define_method(cSignal, "run_last?", query_is_G_SIGNAL_RUN_LAST, 0);
877
+ rb_define_method(cSignal, "run_cleanup?", query_is_G_SIGNAL_RUN_CLEANUP, 0);
878
+ rb_define_method(cSignal, "no_recurse?", query_is_G_SIGNAL_NO_RECURSE, 0);
879
+ rb_define_method(cSignal, "detailed?", query_is_G_SIGNAL_DETAILED, 0);
880
+ rb_define_method(cSignal, "action?", query_is_G_SIGNAL_ACTION, 0);
881
+ rb_define_method(cSignal, "no_hooks?", query_is_G_SIGNAL_NO_HOOKS, 0);
882
+
883
+
884
+ /* GConnectFlags */
885
+ G_DEF_CLASS(G_TYPE_CONNECT_FLAGS, "ConnectFlags", mGLib);
886
+ G_DEF_CONSTANTS(cSignal, G_TYPE_CONNECT_FLAGS, "G_");
887
+
888
+ /* GSignalMatchType */
889
+ cSignalMatchType = G_DEF_CLASS(G_TYPE_SIGNAL_MATCH_TYPE,
890
+ "SignalMatchType", mGLib);
891
+ G_DEF_CONSTANTS(cSignal, G_TYPE_SIGNAL_MATCH_TYPE, "G_SIGNAL_");
892
+ rb_define_const(cSignalMatchType, "MASK", INT2NUM(G_SIGNAL_MATCH_MASK));
893
+ rb_define_const(cSignal, "MATCH_MASK", INT2NUM(G_SIGNAL_MATCH_MASK));
894
+
895
+ rb_define_const(cSignal, "TYPE_STATIC_SCOPE", INT2FIX(G_SIGNAL_TYPE_STATIC_SCOPE));
896
+
897
+ eNoSignalError = rb_define_class_under(mGLib, "NoSignalError", rb_eNameError);
898
+ }
899
+
900
+ /**********************************************************************/
901
+
902
+ void
903
+ rbgobj_define_action_methods(VALUE klass)
904
+ {
905
+ GType gtype = CLASS2GTYPE(klass);
906
+ GString* source;
907
+ guint n_ids;
908
+ guint* ids;
909
+ int i;
910
+
911
+ if (gtype == G_TYPE_INTERFACE)
912
+ return;
913
+
914
+ ids = g_signal_list_ids(gtype, &n_ids);
915
+ if (n_ids == 0)
916
+ return;
917
+
918
+ source = g_string_new(NULL);
919
+ for (i = 0; i < n_ids; i++){
920
+ GSignalQuery query;
921
+ g_signal_query(ids[i], &query);
922
+
923
+ if (query.signal_flags & G_SIGNAL_ACTION) {
924
+ gchar* method_name = g_strdup(query.signal_name);
925
+ gchar* p;
926
+ GString* args;
927
+ int j;
928
+
929
+ for (p = method_name; *p; p++)
930
+ if (*p == '-')
931
+ *p = '_';
932
+
933
+ args = g_string_new(NULL);
934
+ for (j = 0; j < query.n_params; j++)
935
+ g_string_append_printf(args, ",x%d", j);
936
+
937
+ g_string_append_printf(
938
+ source,
939
+ "def %s(%s)\n signal_emit('%s'%s)\nend\n",
940
+ method_name,
941
+ (query.n_params > 0) ? args->str + 1 : "", // hack
942
+ query.signal_name,
943
+ args->str);
944
+
945
+ g_free(method_name);
946
+ g_string_free(args, TRUE);
947
+ }
948
+ }
949
+
950
+ if (source->len > 0)
951
+ rb_funcall(klass, rb_intern("module_eval"), 1, rb_str_new2(source->str));
952
+ g_string_free(source, TRUE);
953
+ }
954
+
955
+ /**********************************************************************/
956
+
957
+ void
958
+ Init_gobject_gsignal()
959
+ {
960
+ Init_signal_class();
961
+ Init_signal_misc();
962
+ }
963
+