diff options
author | Matthias Clasen <mclasen@redhat.com> | 2011-01-30 22:37:30 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2011-01-30 23:00:12 -0500 |
commit | b448bb81cea589e6da9b6b61eb8dace7b6509598 (patch) | |
tree | ac09e5729ee740ab64fcccc55c99b84a4ca99330 /gtk/gtkbindings.c | |
parent | dcf3430e17d3706285e07496f3105df896977e52 (diff) | |
download | gtk+-b448bb81cea589e6da9b6b61eb8dace7b6509598.tar.gz |
Move GtkBindings docs inline
Diffstat (limited to 'gtk/gtkbindings.c')
-rw-r--r-- | gtk/gtkbindings.c | 244 |
1 files changed, 171 insertions, 73 deletions
diff --git a/gtk/gtkbindings.c b/gtk/gtkbindings.c index f6e56862a0..69598e9c5a 100644 --- a/gtk/gtkbindings.c +++ b/gtk/gtkbindings.c @@ -37,6 +37,103 @@ #include "gtkrc.h" #include "gtkintl.h" +/** + * SECTION:gtkbindings + * @Title: GtkBindings + * @Short_description: Key bindings for individual widgets + * @See_also: <link linkend="gtk-keyboard-accelerators">Keyboard Accelerators</link>, #GtkCssProvider + * + * GtkBinding provides a mechanism for configuring GTK+ key bindings + * through CSS files. This eases key binding adjustments for application + * developers as well as users and provides GTK+ users or administrators + * with high key binding configurability which requires no application + * or toolkit side changes. + * + * <refsect2 id="gtk-bindings-install"> + * <title>Installing a key binding</title> + * <para> + * A CSS file binding consists of a 'binding-set' definition and a match + * statement to apply the binding set to specific widget types. Details + * on the matching mechanism are described under + * <link linkend="gtkcssprovider-selectors">Selectors</link> + * in the #GtkCssProvider documentation. Inside the binding-set definition, + * key combinations are bound to one or more specific signal emissions on + * the target widget. Key combinations are strings consisting of an optional + * #GdkModifierType name and <link linkend="gdk-Keyboard-Handling">key names</link> + * such as those defined in <filename><gdk/gdkkeysyms.h></filename> + * or returned from gdk_keyval_name(), they have to be parsable by + * gtk_accelerator_parse(). Specifications of signal emissions consist + * of a string identifying the signal name, and a list of signal specific + * arguments in parenthesis. + * </para> + * <para> + * For example for binding Control and the left or right cursor keys + * of a #GtkEntry widget to the #GtkEntry::move-cursor signal (so movement + * occurs in 3-character steps), the following binding can be used: + * <informalexample><programlisting> + * @binding-set "MoveCursor3" + * { + * bind "<Control>Right" { "move-cursor" (visual-positions, 3, 0) }; + * bind "<Control>Left" { "move-cursor" (visual-positions, -3, 0) }; + * }; + * GtkEntry + * { + * gtk-key-bindings: MoveCursor3 + * } + * </programlisting></informalexample> + * </para> + * </refsect2> + * <refsect2 id="gtk-bindings-unbind"> + * <title>Unbinding existing key bindings</title> + * <para> + * GTK+ already defines a number of useful bindings for the widgets + * it provides. Because custom bindings set up in CSS files take + * precedence over the default bindings shipped with GTK+, overriding + * existing bindings as demonstrated in + * <link linkend="gtk-bindings-install">Installing a key binding</link> + * works as expected. The same mechanism can not be used to "unbind" + * existing bindings, however. + * <informalexample><programlisting> + * @binding-set "MoveCursor3" + * { + * bind "<Control>Right" { }; + * bind "<Control>Left" { }; + * }; + * GtkEntry + * { + * gtk-key-bindings: MoveCursor3 + * } + * </programlisting></informalexample> + * The above example will not have the desired effect of causing + * "<Control>Right" and "<Control>Left" key presses to + * be ignored by GTK+. Instead, it just causes any existing bindings + * from the bindings set "MoveCursor3" to be deleted, so when + * "<Control>Right" or "<Control>Left" are pressed, no + * binding for these keys is found in binding set "MoveCursor3". + * GTK+ will thus continue to search for matching key bindings, and will + * eventually lookup and find the default GTK+ bindings for entries which + * implement word movement. To keep GTK+ from activating its default + * bindings, the "unbind" keyword can be used like this: + * <informalexample><programlisting> + * @binding-set "MoveCursor3" + * { + * unbind "<Control>Right"; + * unbind "<Control>Left"; + * }; + * GtkEntry + * { + * gtk-key-bindings: MoveCursor3 + * } + * </programlisting></informalexample> + * Now, GTK+ will find a match when looking up "<Control>Right" + * and "<Control>Left" key presses before it resorts to its default + * bindings, and the match instructs it to abort ("unbind") the search, + * so the key presses are not consumed by this widget. As usual, further + * processing of the key presses, e.g. by an entry's parent widget, is + * now possible. + * </para> + * </refsect2> + */ /* --- defines --- */ #define BINDING_MOD_MASK() (gtk_accelerator_get_default_mod_mask () | GDK_RELEASE_MASK) @@ -100,7 +197,7 @@ binding_signal_new (const gchar *signal_name, signal->signal_name = (gchar *)g_intern_string (signal_name); signal->n_args = n_args; signal->args = (GtkBindingArg *)(signal + 1); - + return signal; } @@ -108,7 +205,7 @@ static void binding_signal_free (GtkBindingSignal *sig) { guint i; - + for (i = 0; i < sig->n_args; i++) { if (G_TYPE_FUNDAMENTAL (sig->args[i].arg_type) == G_TYPE_STRING) @@ -144,7 +241,7 @@ binding_key_hash_insert_entry (GtkKeyHash *key_hash, GtkBindingEntry *entry) { guint keyval = entry->keyval; - + /* We store lowercased accelerators. To deal with this, if <Shift> * was specified, uppercase. */ @@ -155,7 +252,7 @@ binding_key_hash_insert_entry (GtkKeyHash *key_hash, else keyval = gdk_keyval_to_upper (keyval); } - + _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers & ~GDK_RELEASE_MASK, entry); } @@ -163,7 +260,7 @@ static void binding_key_hash_destroy (gpointer data) { GtkKeyHash *key_hash = data; - + binding_key_hashes = g_slist_remove (binding_key_hashes, key_hash); _gtk_key_hash_free (key_hash); } @@ -188,7 +285,7 @@ binding_key_hash_for_keymap (GdkKeymap *keymap) if (!key_hash_quark) key_hash_quark = g_quark_from_static_string ("gtk-binding-key-hash"); - + key_hash = g_object_get_qdata (G_OBJECT (keymap), key_hash_quark); if (!key_hash) @@ -215,7 +312,7 @@ binding_entry_new (GtkBindingSet *binding_set, { GSList *tmp_list; GtkBindingEntry *entry; - + if (!binding_entry_hash_table) binding_entry_hash_table = g_hash_table_new (binding_entry_hash, binding_entries_compare); @@ -256,12 +353,12 @@ binding_entry_free (GtkBindingEntry *entry) entry->destroyed == TRUE); entry->destroyed = FALSE; - + sig = entry->signals; while (sig) { GtkBindingSignal *prev; - + prev = sig; sig = prev->next; binding_signal_free (prev); @@ -296,7 +393,7 @@ binding_entry_destroy (GtkBindingEntry *entry) tmp = last->set_next; } entry->set_next = NULL; - + o_entry = g_hash_table_lookup (binding_entry_hash_table, entry); begin = o_entry; last = NULL; @@ -315,7 +412,7 @@ binding_entry_destroy (GtkBindingEntry *entry) tmp = last->hash_next; } entry->hash_next = NULL; - + if (!begin) g_hash_table_remove (binding_entry_hash_table, entry); else if (begin != o_entry) @@ -343,13 +440,13 @@ binding_ht_lookup_entry (GtkBindingSet *set, { GtkBindingEntry lookup_entry = { 0 }; GtkBindingEntry *entry; - + if (!binding_entry_hash_table) return NULL; - + lookup_entry.keyval = keyval; lookup_entry.modifiers = modifiers; - + entry = g_hash_table_lookup (binding_entry_hash_table, &lookup_entry); for (; entry; entry = entry->hash_next) if (entry->binding_set == set) @@ -368,7 +465,7 @@ binding_compose_params (GObject *object, const GType *types; guint i; gboolean valid; - + params = g_new0 (GValue, query->n_params + 1); *params_p = params; @@ -377,7 +474,7 @@ binding_compose_params (GObject *object, g_value_init (params, G_TYPE_OBJECT); g_value_set_object (params, G_OBJECT (object)); params++; - + types = query->param_types; valid = TRUE; for (i = 1; i < query->n_params + 1 && valid; i++) @@ -466,23 +563,23 @@ binding_compose_params (GObject *object, g_value_unset (&tmp_value); } - + types++; params++; args++; } - + if (!valid) { guint j; for (j = 0; j < i; j++) g_value_unset (&(*params_p)[j]); - + g_free (*params_p); *params_p = NULL; } - + return valid; } @@ -494,12 +591,12 @@ gtk_binding_entry_activate (GtkBindingEntry *entry, gboolean old_emission; gboolean handled = FALSE; gint i; - + old_emission = entry->in_emission; entry->in_emission = TRUE; - + g_object_ref (object); - + for (sig = entry->signals; sig; sig = sig->next) { GSignalQuery query; @@ -507,7 +604,7 @@ gtk_binding_entry_activate (GtkBindingEntry *entry, GValue *params = NULL; GValue return_val = { 0, }; gchar *accelerator = NULL; - + signal_id = g_signal_lookup (sig->signal_name, G_OBJECT_TYPE (object)); if (!signal_id) { @@ -551,7 +648,7 @@ gtk_binding_entry_activate (GtkBindingEntry *entry, if (query.return_type == G_TYPE_BOOLEAN) g_value_init (&return_val, G_TYPE_BOOLEAN); - + g_signal_emitv (params, signal_id, 0, &return_val); if (query.return_type == G_TYPE_BOOLEAN) @@ -562,15 +659,15 @@ gtk_binding_entry_activate (GtkBindingEntry *entry, } else handled = TRUE; - + for (i = 0; i < query.n_params + 1; i++) g_value_unset (¶ms[i]); g_free (params); - + if (entry->destroyed) break; } - + g_object_unref (object); entry->in_emission = old_emission; @@ -593,9 +690,9 @@ GtkBindingSet* gtk_binding_set_new (const gchar *set_name) { GtkBindingSet *binding_set; - + g_return_val_if_fail (set_name != NULL, NULL); - + binding_set = g_new (GtkBindingSet, 1); binding_set->set_name = (gchar *) g_intern_string (set_name); binding_set->widget_path_pspecs = NULL; @@ -604,9 +701,9 @@ gtk_binding_set_new (const gchar *set_name) binding_set->entries = NULL; binding_set->current = NULL; binding_set->parsed = FALSE; - + binding_set_list = g_slist_prepend (binding_set_list, binding_set); - + return binding_set; } @@ -651,9 +748,10 @@ gtk_binding_set_by_class (gpointer object_class) * gtk_binding_set_find: * @set_name: unique binding set name * - * Find a binding set by its globally unique name. The @set_name can - * either be a name used for gtk_binding_set_new() or the type name of - * a class used in gtk_binding_set_by_class(). + * Find a binding set by its globally unique name. + * + * The @set_name can either be a name used for gtk_binding_set_new() + * or the type name of a class used in gtk_binding_set_by_class(). * * Return value: (transfer none): %NULL or the specified binding set */ @@ -661,13 +759,13 @@ GtkBindingSet* gtk_binding_set_find (const gchar *set_name) { GSList *slist; - + g_return_val_if_fail (set_name != NULL, NULL); - + for (slist = binding_set_list; slist; slist = slist->next) { GtkBindingSet *binding_set; - + binding_set = slist->data; if (g_str_equal (binding_set->set_name, (gpointer) set_name)) return binding_set; @@ -694,17 +792,17 @@ gtk_binding_set_activate (GtkBindingSet *binding_set, GObject *object) { GtkBindingEntry *entry; - + g_return_val_if_fail (binding_set != NULL, FALSE); g_return_val_if_fail (G_IS_OBJECT (object), FALSE); - + keyval = gdk_keyval_to_lower (keyval); modifiers = modifiers & BINDING_MOD_MASK (); - + entry = binding_ht_lookup_entry (binding_set, keyval, modifiers); if (entry) return gtk_binding_entry_activate (entry, object); - + return FALSE; } @@ -772,12 +870,12 @@ gtk_binding_entry_remove (GtkBindingSet *binding_set, GdkModifierType modifiers) { GtkBindingEntry *entry; - + g_return_if_fail (binding_set != NULL); - + keyval = gdk_keyval_to_lower (keyval); modifiers = modifiers & BINDING_MOD_MASK (); - + entry = binding_ht_lookup_entry (binding_set, keyval, modifiers); if (entry) binding_entry_destroy (entry); @@ -819,20 +917,20 @@ _gtk_binding_entry_add_signall (GtkBindingSet *binding_set, GSList *slist; guint n = 0; GtkBindingArg *arg; - + g_return_if_fail (binding_set != NULL); g_return_if_fail (signal_name != NULL); - + keyval = gdk_keyval_to_lower (keyval); modifiers = modifiers & BINDING_MOD_MASK (); - + signal = binding_signal_new (signal_name, g_slist_length (binding_args)); - + arg = signal->args; for (slist = binding_args; slist; slist = slist->next) { GtkBindingArg *tmp_arg; - + tmp_arg = slist->data; if (!tmp_arg) { @@ -872,7 +970,7 @@ _gtk_binding_entry_add_signall (GtkBindingSet *binding_set, arg++; n++; } - + entry = binding_ht_lookup_entry (binding_set, keyval, modifiers); if (!entry) { @@ -913,7 +1011,7 @@ gtk_binding_entry_add_signal (GtkBindingSet *binding_set, g_return_if_fail (binding_set != NULL); g_return_if_fail (signal_name != NULL); - + va_start (args, n_args); slist = NULL; for (i = 0; i < n_args; i++) @@ -1255,7 +1353,7 @@ create_signal_scanner (void) * it into @binding_set. * * signal descriptions may either bind a key combination to - * a signal: + * one or more signals: * <informalexample><programlisting> * bind <replaceable>key</replaceable> { * <replaceable>signalname</replaceable> (<replaceable>param</replaceable>, ...) @@ -1302,10 +1400,10 @@ gtk_binding_entry_add_signal_from_string (GtkBindingSet *binding_set, /** * gtk_binding_set_add_path: - * @binding_set: a #GtkBindingSet to add a path to - * @path_type: path type the pattern applies to + * @binding_set: a #GtkBindingSet to add a path to + * @path_type: path type the pattern applies to * @path_pattern: the actual match pattern - * @priority: binding priority + * @priority: binding priority * * This function is used internally by the GtkRC parsing mechanism to * assign match patterns to #GtkBindingSet structures. @@ -1313,21 +1411,21 @@ gtk_binding_entry_add_signal_from_string (GtkBindingSet *binding_set, * Deprecated: 3.0 */ void -gtk_binding_set_add_path (GtkBindingSet *binding_set, - GtkPathType path_type, - const gchar *path_pattern, - GtkPathPriorityType priority) +gtk_binding_set_add_path (GtkBindingSet *binding_set, + GtkPathType path_type, + const gchar *path_pattern, + GtkPathPriorityType priority) { PatternSpec *pspec; GSList **slist_p, *slist; static guint seq_id = 0; - + g_return_if_fail (binding_set != NULL); g_return_if_fail (path_pattern != NULL); g_return_if_fail (priority <= GTK_PATH_PRIO_MASK); priority &= GTK_PATH_PRIO_MASK; - + switch (path_type) { case GTK_PATH_WIDGET: @@ -1344,7 +1442,7 @@ gtk_binding_set_add_path (GtkBindingSet *binding_set, slist_p = NULL; break; } - + pspec = g_new (PatternSpec, 1); pspec->type = path_type; if (path_type == GTK_PATH_WIDGET_CLASS) @@ -1354,15 +1452,15 @@ gtk_binding_set_add_path (GtkBindingSet *binding_set, pspec->seq_id = priority << 28; pspec->user_data = binding_set; - + slist = *slist_p; while (slist) { PatternSpec *tmp_pspec; - + tmp_pspec = slist->data; slist = slist->next; - + if (g_pattern_spec_equal (tmp_pspec->pspec, pspec->pspec)) { GtkPathPriorityType lprio = tmp_pspec->seq_id >> 28; @@ -1425,9 +1523,9 @@ binding_activate (GtkBindingSet *binding_set, } static gboolean -gtk_bindings_activate_list (GObject *object, - GSList *entries, - gboolean is_release) +gtk_bindings_activate_list (GObject *object, + GSList *entries, + gboolean is_release) { GtkStyleContext *context; GtkBindingSet *binding_set; @@ -1521,7 +1619,7 @@ gtk_bindings_activate (GObject *object, display = gtk_widget_get_display (GTK_WIDGET (object)); key_hash = binding_key_hash_for_keymap (gdk_keymap_get_for_display (display)); - + entries = _gtk_key_hash_lookup_keyval (key_hash, keyval, modifiers); handled = gtk_bindings_activate_list (object, entries, is_release); @@ -1535,10 +1633,10 @@ gtk_bindings_activate (GObject *object, * gtk_bindings_activate_event: * @object: a #GObject (generally must be a widget) * @event: a #GdkEventKey - * + * * Looks up key bindings for @object to find one matching * @event, and if one was found, activate it. - * + * * Return value: %TRUE if a matching key binding was found * * Since: 2.4 @@ -1563,7 +1661,7 @@ gtk_bindings_activate_event (GObject *object, event->state, BINDING_MOD_MASK () & ~GDK_RELEASE_MASK, event->group); - + handled = gtk_bindings_activate_list (object, entries, event->type == GDK_KEY_RELEASE); |