File: GtkBindings.xs

package info (click to toggle)
libgtk2-perl 2:1.2499-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 4,668 kB
  • ctags: 594
  • sloc: perl: 22,100; ansic: 122; makefile: 17
file content (440 lines) | stat: -rw-r--r-- 14,332 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
/*
 * Copyright 2009 by the gtk2-perl team (see the file AUTHORS)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */

#include "gtk2perl.h"

/* GtkBindingSet is a struct treated here as a boxed type.  As of Gtk 2.12
   there's no GType for it, so that's created here, with a #ifndef in
   gtk2perl.h in case gtk gains it later.

   Once created a GtkBindingSet is never destroyed, so no ref counting and
   no distinction between "own" and "copy".

   ENHANCE-ME: Currently there's nothing to retrieve the contents of a
   bindingset at the perl level.  The widget_path_pspecs and other pspecs
   use a private PatternMatch struct so are inaccessible.  The linked list
   of GtkBindingEntry and their contained GtkBindingSignal might be
   extracted though, maybe in some form tolerably close to the kind of
   entry_add_signal() calls that would build the set.  */

static GtkBindingSet *
gtk2perl_binding_set_copy (GtkBindingSet *binding_set)
{
	/* no copying */
	return binding_set;
}
static void
gtk2perl_binding_set_free (GtkBindingSet *binding_set)
{
	PERL_UNUSED_VAR (binding_set);
	/* no freeing */
}
GType
gtk2perl_binding_set_get_type (void)
{
	static GType binding_set_type = 0;
	if (binding_set_type == 0)
		binding_set_type = g_boxed_type_register_static
			("GtkBindingSet",
			 (GBoxedCopyFunc) gtk2perl_binding_set_copy,
			 (GBoxedFreeFunc) gtk2perl_binding_set_free);
	return binding_set_type;
}

MODULE = Gtk2::BindingSet	PACKAGE = Gtk2::BindingSet

=for position DESCRIPTION

=head1 DESCRIPTION

A C<Gtk2::BindingSet> is basically a mapping from keyval+modifiers to
a named action signal to invoke and with argument values for the
signal.  Bindings are normally run by the C<Gtk2::Widget> default
C<key-press-event> handler, but can also be activated explicitly.

Binding sets can be populated from program code with
C<entry_add_signal>, or created from an RC file or string (see
L<Gtk2::Rc>).  If you use the RC note it doesn't parse and create
anything until there's someone interested in the result, such as
C<Gtk2::Settings> for widgets.	This means binding sets in RC files or
strings don't exist for C<< Gtk2::BindingSet->find >> to retrieve
until at least one widget has been created (or similar).

Currently there's no Perl-level access to the contents of a
BindingSet, except for C<set_name>.

=cut

## Method name "set_name()" corresponds to the struct field name.  The name
## might make you think it's a setter, like other set_foo() funcs, so the
## couple of words of apidoc here try to make that clear it's a getter,
## without labouring the point.
=for apidoc
Return the name of $binding_set.
=cut
gchar *
set_name (binding_set)
	GtkBindingSet *binding_set
    CODE:
	RETVAL = binding_set->set_name;
    OUTPUT:
	RETVAL

## Note no field accessor for "priority", because as noted in the docs
## it is unused nowadays, and in fact contains garbage.	 (The priority
## from add_path() is buried in the private PatternSpec struct,
## establishing an order among the matches, and different places using
## the same GtkBindingSet can have different priorities ...)

MODULE = Gtk2::BindingSet	PACKAGE = Gtk2::BindingSet	PREFIX = gtk_binding_set_

## Is/was gtk_binding_entry_clear() something subtly different from
## gtk_binding_entry_remove()?	The code for the two is different as
## of Gtk circa 2.16.
##
## void
## gtk_binding_entry_clear (binding_set, keyval, modifiers)
##     GtkBindingSet *binding_set
##     guint keyval
##     GdkModifierType modifiers

## GtkBindingSet* gtk_binding_set_new (const gchar *set_name)
## GtkBindingSet* gtk_binding_set_find (const gchar *set_name)
## GtkBindingSet* gtk_binding_set_by_class (gpointer object_class)
##
## gtk_binding_set_new() copies the given set_name, so the string need
## not live beyond the call
##
## Only gtk_binding_set_find() needs the "ornull" return, new() and
## by_class() are never NULL.
##
## In other wrappers normally new() would be an "_own", find() not,
## and by_class() probably not, but as noted at the start of the file
## there's no copying or freeing of GtkBindingSet so no such
## distinction needed here.
##
=for apidoc Gtk2::BindingSet::new
=for signature GtkBindingSet = Gtk2::BindingSet->new ($set_name)
=for arg set_name (string)
=for arg name (__hide__)
=cut

=for apidoc Gtk2::BindingSet::find
=for signature GtkBindingSet_ornull Gtk2::BindingSet->find ($set_name)
=for arg set_name (string)
=for arg name (__hide__)
=cut

=for apidoc Gtk2::BindingSet::by_class
=for signature GtkBindingSet = Gtk2::BindingSet->by_class ($package_name)
=for arg package_name (string)
=for arg name (__hide__)
=cut

=for apidoc new __hide__
=for apidoc find __hide__
=for apidoc by_class __hide__
=cut
GtkBindingSet_ornull* gtk_binding_set_new (class, name)
	const gchar *name
    ALIAS:
	find = 1
	by_class = 2
    CODE:
	switch (ix) {
	case 0:
		RETVAL = gtk_binding_set_new (name);
		break;
	case 1:
		RETVAL = gtk_binding_set_find (name);
		break;
	default:
	    {
		GType type;
		GtkObjectClass *oclass;
		type = gperl_object_type_from_package (name);
		if (! type)
			croak ("package %s is not registered to a GType",
			       name);
		if (! g_type_is_a (type, GTK_TYPE_OBJECT))
			croak ("'%s' is not an object subclass", name);
		oclass = (GtkObjectClass*) g_type_class_ref (type);
		RETVAL = gtk_binding_set_by_class (oclass);
		g_type_class_unref (oclass);
	    }
	    break;
	}
    OUTPUT:
	RETVAL

gboolean
gtk_binding_set_activate (binding_set, keyval, modifiers, object)
     GtkBindingSet *binding_set
     guint keyval
     GdkModifierType modifiers
     GtkObject *object

=for apidoc
The following constants are defined for standard priority levels,

    Gtk2::GTK_PATH_PRIO_LOWEST
    Gtk2::GTK_PATH_PRIO_GTK
    Gtk2::GTK_PATH_PRIO_APPLICATION
    Gtk2::GTK_PATH_PRIO_THEME
    Gtk2::GTK_PATH_PRIO_RC
    Gtk2::GTK_PATH_PRIO_HIGHEST

LOWEST, which is 0, and HIGHEST, which is 15, are the limits of the
allowed priorities.  The standard values are from the
C<Gtk2::PathPriorityType> enum, but the parameter here is an integer,
not an enum string, so you can give a value for instance a little
above or below the pre-defined levels.
=cut
void
gtk_binding_set_add_path (binding_set, path_type, path_pattern, priority)
     GtkBindingSet *binding_set
     GtkPathType path_type
     const gchar *path_pattern
     int priority

MODULE = Gtk2::BindingSet	PACKAGE = Gtk2::BindingSet	PREFIX = gtk_binding_

=for apidoc
=for signature $binding_set->entry_add_signal ($keyval, $modifiers, $signal_name)
=for signature $binding_set->entry_add_signal ($keyval, $modifiers, $signal_name, $type,$value, ...)
=for arg type (string)
=for arg value (scalar)
=for arg ... (__hide__)
Add an entry to $binding_set.  $keyval and $modifier are setup as a
binding for $signal_name and with signal parameters given by $value
arguments.  Each value is preceded by a type (a string), which must be
one of

    Glib::Long
    Glib::Double
    Glib::String
    an enum type, ie. subtype of Glib::Enum
    Glib::Flags, or a flags subtype

For example,

    $binding_set->entry_add_signal
	(Gtk2->keyval_from_name('Return'),
	 [ 'control-mask' ],   # modifiers
	 'some-signal-name',
	 'Glib::Double', 1.5,
	 'Glib::String,	 'hello');

A parameter holds one of the three types Long, Double or String.  When
invoked they're coerced to the parameter types expected by the target
object or widget.  Use Glib::Long for any integer argument, including
chars and unichars by ordinal value.  Use Glib::Double for both single
and double precision floats.

Flags and enums are held as Longs in the BindingSet.  You can pass an
enum type and string and C<entry_with_signal> will lookup and store
accordingly.  For example

    $binding_set->entry_add_signal
	(Gtk2->keyval_from_name('Escape), [],
	 'set-direction',
	 'Gtk2::Orientation', 'vertical');

Likewise flags from an arrayref,

    $binding_set->entry_add_signal
	(Gtk2->keyval_from_name('d'), [],
	 'initiate-drag',
	 'Gtk2::Gdk::DragAction', ['move,'ask']);

If you've got a Glib::Flags object, rather than just an arrayref, then
you can just give Glib::Flags as the type and the value is taken from
the object.  For example,

    my $flags = Gtk2::DebugFlag->new (['tree', 'updates']);
    $binding_set->entry_add_signal
	(Gtk2->keyval_from_name('x'), ['control-mask'],
	 'change-debug',
	 'Glib::Flags', $flags);
=cut
## The list style "_signall" version is best here, rather than the
## varargs "_signal".  "_signall" is marked as "deprecated" circa Gtk
## 2.12.  Of course deprecated is not a word but in this case it means
## "useful feature taken away".	 As of Gtk 2.16 _signal is in fact
## implemented as a front end to _signall, though with some extra
## coercions on the args, allowing for instance GValue containing
## G_TYPE_INT to promote to G_TYPE_LONG.
##
## void gtk_binding_entry_add_signall (GtkBindingSet *binding_set,
##				       guint keyval,
##				       GdkModifierType modifiers,
##				       const gchar *signal_name,
##				       GSList *binding_args);
##
## void gtk_binding_entry_add_signal (GtkBindingSet *binding_set,
##				      guint keyval,
##				      GdkModifierType modifiers,
##				      const gchar *signal_name,
##				      guint n_args,
##				      ...);
##
## There may be some scope for expanding the helper "type"s accepted.
## For example 'Glib::Boolean' could take the usual perl true/false
## and turn it into 0 or 1.  Or 'Glib::Unichar' could take a single
## char string and store its ordinal.  Both can be done with
## 'Glib::Long' and a "!!" boolizing or ord() lookup, so it's just
## about what would be helpful and what would be useless bloat.	 The
## Flags and Enum provided are quite helpful because it's not
## particularly easy to extract the number.  A Unichar would probably
## be bloat since there's no signals which take a char ordinal as a
## parameter, is there?
##
void
gtk_binding_entry_add_signal (binding_set, keyval, modifiers, signal_name, ...)
	GtkBindingSet *binding_set
	guint keyval
	GdkModifierType modifiers
	const gchar *signal_name
    PREINIT:
	const int first_argnum = 4;
	int count, i;
	GSList *binding_args = NULL;
	GtkBindingArg *ap;
    CODE:
	count = (items - first_argnum);
	if ((count % 2) != 0) {
		croak ("entry_add_signal expects type,value pairs "
		       "(odd number of arguments detected)");
	}
	count /= 2;
	ap = g_new (GtkBindingArg, count);
	for (i = 0; i < count; i += 2) {
		SV *sv_type  = ST(i + first_argnum);
		SV *sv_value = ST(i + first_argnum + 1);
		GType gtype  = gperl_type_from_package(SvPV_nolen(sv_type));

		/* gtype==G_TYPE_NONE if sv_type is not registered; it falls
		 * through to the "default:" error
		 */
		switch (G_TYPE_FUNDAMENTAL (gtype)) {
		case G_TYPE_LONG:
			ap[i].d.long_data = SvIV(sv_value);
			break;
		case G_TYPE_DOUBLE:
			ap[i].d.double_data = SvNV(sv_value);
			break;
		case G_TYPE_STRING:
			/* GTK_TYPE_IDENTIFIER comes through here, but
			 * believe that's only a hangover from gtk 1.2 and
			 * needs no special attention.
			 */
			/* gtk copies the string */
			ap[i].d.string_data = SvPV_nolen(sv_value);
			break;

		/* helpers converting to the three basic types ... */
		case G_TYPE_ENUM:
			/* coerce enum to long */
			ap[i].d.long_data = gperl_convert_enum(gtype,sv_value);
			gtype = G_TYPE_LONG;
			break;
		case G_TYPE_FLAGS:
			/* coerce flags to long */
			ap[i].d.long_data = gperl_convert_flags(gtype,sv_value);
			gtype = G_TYPE_LONG;
			break;

		default:
			g_slist_free (binding_args);
			g_free (ap);
			croak ("Unrecognised argument type '%s'",
				SvPV_nolen(sv_type));
		}
		ap[i].arg_type = gtype;
		binding_args = g_slist_append (binding_args, &(ap[i]));
	}
	gtk_binding_entry_add_signall (binding_set, keyval, modifiers,
				       signal_name, binding_args);
	g_slist_free (binding_args);
	g_free (ap);

## void gtk_binding_entry_remove (GtkBindingSet *binding_set,
##				  guint keyval,
##				  GdkModifierType modifiers);
void
gtk_binding_entry_remove (binding_set, keyval, modifiers)
	GtkBindingSet *binding_set
	guint keyval
	GdkModifierType modifiers
    CODE:
	gtk_binding_entry_remove (binding_set, keyval, modifiers);

#if GTK_CHECK_VERSION (2, 12, 0)

## void gtk_binding_entry_skip (GtkBindingSet *binding_set,
##				guint keyval,
##				GdkModifierType modifiers);
void
gtk_binding_entry_skip (binding_set, keyval, modifiers)
	GtkBindingSet *binding_set
	guint keyval
	GdkModifierType modifiers
    CODE:
	gtk_binding_entry_skip (binding_set, keyval, modifiers);

#endif


MODULE = Gtk2::BindingSet	PACKAGE = Gtk2::Object	PREFIX = gtk_

=for apidoc
Although C<activate> and C<activate_event> are C<Gtk2::Object>
methods, as of Gtk 2.12 binding sets are only associated with widgets
so on an object as such the return is always false (no binding
activated).

Further, although C<activate> and binding sets are both expressed in
terms of keyvals, internally the lookup is by keycode.  If a keyval
cannot be generated by at least one keycode/modifier combination (see
L<Gtk2::Gdk::Keymap>) then it cannot be activated.  In particular this
means keyvals like C<Pointer_Button1> which are not actual keys cannot
be dispatched by C<activate> (returning false for no binding
activated).
=cut
gboolean
gtk_bindings_activate (object, keyval, modifiers)
	GtkObject *object
	guint keyval
	GdkModifierType modifiers

#if GTK_CHECK_VERSION(2, 4, 0)

gboolean
gtk_bindings_activate_event (object, event)
	GtkObject *object
	GdkEvent *event
PREINIT:
	GdkEventType type;
CODE:
	type = event->type;
	if (type != GDK_KEY_PRESS && type != GDK_KEY_RELEASE)
		croak ("Event must be key-press or key-release");
	RETVAL = gtk_bindings_activate_event (object, (GdkEventKey*) event);
OUTPUT:
	RETVAL

#endif