X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkaccelgroup.c;h=c2d91028fd68a9b55802b3c84dbe4a24c53a7ee3;hb=8a17cad2e5e3f14e0a8977f069cbe8b8a83eaf48;hp=f131d065fd28aed9ed99e72123077874514bacd1;hpb=4a44f3f6e1ebbc63a3d52522deb8be58acb5bc86;p=~andy%2Fgtk diff --git a/gtk/gtkaccelgroup.c b/gtk/gtkaccelgroup.c index f131d065f..c2d91028f 100644 --- a/gtk/gtkaccelgroup.c +++ b/gtk/gtkaccelgroup.c @@ -12,9 +12,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ /* @@ -31,11 +29,10 @@ #include "gtkaccelgroup.h" #include "gtkaccelgroupprivate.h" #include "gtkaccellabel.h" -#include "gtkaccelmap.h" +#include "gtkaccelmapprivate.h" #include "gtkintl.h" -#include "gtkmainprivate.h" #include "gtkmarshalers.h" - +#include "gtkprivate.h" /** * SECTION:gtkaccelgroup @@ -62,8 +59,6 @@ * and mnemonics, of course. */ -#define GTK_ACCEL_GROUP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_ACCEL_GROUP, GtkAccelGroupPrivate)) - /* --- prototypes --- */ static void gtk_accel_group_finalize (GObject *object); static void gtk_accel_group_get_property (GObject *object, @@ -154,7 +149,7 @@ gtk_accel_group_class_init (GtkAccelGroupClass *class) * @modifier: the modifier combination of the accelerator * @accel_closure: the #GClosure of the accelerator * - * The accel-changed signal is emitted when a #GtkAccelGroupEntry + * The accel-changed signal is emitted when an entry * is added to or removed from the accel group. * * Widgets like #GtkAccelLabel which display an associated @@ -228,22 +223,26 @@ gtk_accel_group_get_property (GObject *object, static void gtk_accel_group_init (GtkAccelGroup *accel_group) { - GtkAccelGroupPrivate *priv = GTK_ACCEL_GROUP_GET_PRIVATE (accel_group); + GtkAccelGroupPrivate *priv; + + accel_group->priv = G_TYPE_INSTANCE_GET_PRIVATE (accel_group, + GTK_TYPE_ACCEL_GROUP, + GtkAccelGroupPrivate); + priv = accel_group->priv; priv->lock_count = 0; priv->modifier_mask = gtk_accelerator_get_default_mod_mask (); priv->acceleratables = NULL; priv->n_accels = 0; priv->priv_accels = NULL; - - accel_group->priv = priv; } /** * gtk_accel_group_new: - * @returns: a new #GtkAccelGroup object * * Creates a new #GtkAccelGroup. + * + * Returns: a new #GtkAccelGroup object */ GtkAccelGroup* gtk_accel_group_new (void) @@ -379,11 +378,12 @@ gtk_accel_groups_from_object (GObject *object) * @find_func: (scope call): a function to filter the entries * of @accel_group with * @data: data to pass to @find_func - * @returns: (transfer none): the key of the first entry passing - * @find_func. The key is owned by GTK+ and must not be freed. * * Finds the first entry in an accelerator group for which * @find_func returns %TRUE and returns its #GtkAccelKey. + * + * Returns: (transfer none): the key of the first entry passing + * @find_func. The key is owned by GTK+ and must not be freed. */ GtkAccelKey* gtk_accel_group_find (GtkAccelGroup *accel_group, @@ -701,12 +701,13 @@ gtk_accel_group_connect_by_path (GtkAccelGroup *accel_group, * @accel_group: the accelerator group to remove an accelerator from * @closure: (allow-none): the closure to remove from this accelerator * group, or %NULL to remove all closures - * @returns: %TRUE if the closure was found and got disconnected * * Removes an accelerator previously installed through * gtk_accel_group_connect(). * * Since 2.20 @closure can be %NULL. + * + * Returns: %TRUE if the closure was found and got disconnected */ gboolean gtk_accel_group_disconnect (GtkAccelGroup *accel_group, @@ -732,11 +733,12 @@ gtk_accel_group_disconnect (GtkAccelGroup *accel_group, * @accel_group: the accelerator group to install an accelerator in * @accel_key: key value of the accelerator * @accel_mods: modifier combination of the accelerator - * @returns: %TRUE if there was an accelerator which could be - * removed, %FALSE otherwise * * Removes an accelerator previously installed through * gtk_accel_group_connect(). + * + * Returns: %TRUE if there was an accelerator which could be + * removed, %FALSE otherwise */ gboolean gtk_accel_group_disconnect_key (GtkAccelGroup *accel_group, @@ -822,12 +824,13 @@ _gtk_accel_group_get_accelerables (GtkAccelGroup *accel_group) * @accel_mods: modifier combination of the accelerator * @n_entries: (allow-none): location to return the number * of entries found, or %NULL - * @returns: (transfer none) (array length=n_entries): an array of - * @n_entries #GtkAccelGroupEntry elements, or %NULL. The array - * is owned by GTK+ and must not be freed. * * Queries an accelerator group for all entries matching @accel_key * and @accel_mods. + * + * Returns: (transfer none) (array length=n_entries): an array of + * @n_entries #GtkAccelGroupEntry elements, or %NULL. The array + * is owned by GTK+ and must not be freed. */ GtkAccelGroupEntry* gtk_accel_group_query (GtkAccelGroup *accel_group, @@ -851,11 +854,12 @@ gtk_accel_group_query (GtkAccelGroup *accel_group, /** * gtk_accel_group_from_accel_closure: * @closure: a #GClosure - * @returns: (transfer none): the #GtkAccelGroup to which @closure - * is connected, or %NULL * * Finds the #GtkAccelGroup to which @closure is connected; * see gtk_accel_group_connect(). + * + * Returns: (transfer none): the #GtkAccelGroup to which @closure + * is connected, or %NULL */ GtkAccelGroup* gtk_accel_group_from_accel_closure (GClosure *closure) @@ -956,13 +960,14 @@ gtk_accel_groups_activate (GObject *object, * gtk_accelerator_valid: * @keyval: a GDK keyval * @modifiers: modifier mask - * @returns: %TRUE if the accelerator is valid * * Determines whether a given keyval and modifier mask constitute * a valid keyboard accelerator. For example, the #GDK_KEY_a keyval * plus #GDK_CONTROL_MASK is valid - this is a "Ctrl+a" accelerator. * But, you can't, for instance, use the #GDK_KEY_Control_L keyval * as an accelerator. + * + * Returns: %TRUE if the accelerator is valid */ gboolean gtk_accelerator_valid (guint keyval, @@ -1144,40 +1149,72 @@ is_hyper (const gchar *string) (string[6] == '>')); } +static inline gboolean +is_primary (const gchar *string) +{ + return ((string[0] == '<') && + (string[1] == 'p' || string[1] == 'P') && + (string[2] == 'r' || string[2] == 'R') && + (string[3] == 'i' || string[3] == 'I') && + (string[4] == 'm' || string[4] == 'M') && + (string[5] == 'a' || string[5] == 'A') && + (string[6] == 'r' || string[6] == 'R') && + (string[7] == 'y' || string[7] == 'Y') && + (string[8] == '>')); +} + +static inline gboolean +is_keycode (const gchar *string) +{ + return (string[0] == '0' && + string[1] == 'x' && + g_ascii_isxdigit (string[2]) && + g_ascii_isxdigit (string[3])); +} + /** - * gtk_accelerator_parse: + * gtk_accelerator_parse_with_keycode: * @accelerator: string representing an accelerator - * @accelerator_key: (out): return location for accelerator keyval - * @accelerator_mods: (out): return location for accelerator modifier mask + * @accelerator_key: (out) (allow-none): return location for accelerator + * keyval, or %NULL + * @accelerator_codes: (out) (allow-none): return location for accelerator + * keycodes, or %NULL + * @accelerator_mods: (out) (allow-none): return location for accelerator + * modifier mask, %NULL * - * Parses a string representing an accelerator. The - * format looks like "<Control>a" or "<Shift><Alt>F1" - * or "<Release>z" (the last one is for key release). + * Parses a string representing an accelerator, similarly to + * gtk_accelerator_parse() but handles keycodes as well. This is only + * useful for system-level components, applications should use + * gtk_accelerator_parse() instead. * - * The parser is fairly liberal and allows lower or upper case, - * and also abbreviations such as "<Ctl>" and "<Ctrl>". - * Key names are parsed using gdk_keyval_from_name(). For character - * keys the name is not the symbol, but the lowercase name, e.g. one - * would use "<Ctrl>minus" instead of "<Ctrl>-". + * If a keycode is present in the accelerator and no @accelerator_codes + * is given, the parse will fail. * - * If the parse fails, @accelerator_key and @accelerator_mods will - * be set to 0 (zero). + * If the parse fails, @accelerator_key, @accelerator_mods and + * @accelerator_codes will be set to 0 (zero). + * + * Since: 3.4 */ void -gtk_accelerator_parse (const gchar *accelerator, - guint *accelerator_key, - GdkModifierType *accelerator_mods) +gtk_accelerator_parse_with_keycode (const gchar *accelerator, + guint *accelerator_key, + guint **accelerator_codes, + GdkModifierType *accelerator_mods) { guint keyval; GdkModifierType mods; gint len; + gboolean error; if (accelerator_key) *accelerator_key = 0; if (accelerator_mods) *accelerator_mods = 0; + if (accelerator_codes) + *accelerator_codes = NULL; g_return_if_fail (accelerator != NULL); + error = FALSE; keyval = 0; mods = 0; len = strlen (accelerator); @@ -1191,6 +1228,12 @@ gtk_accelerator_parse (const gchar *accelerator, len -= 9; mods |= GDK_RELEASE_MASK; } + else if (len >= 9 && is_primary (accelerator)) + { + accelerator += 9; + len -= 9; + mods |= _gtk_get_primary_accel_mod (); + } else if (len >= 9 && is_control (accelerator)) { accelerator += 9; @@ -1272,18 +1315,191 @@ gtk_accelerator_parse (const gchar *accelerator, } else { - keyval = gdk_keyval_from_name (accelerator); + if (len >= 4 && is_keycode (accelerator)) + { + char keystring[5]; + gchar *endptr; + gint tmp_keycode; + + memcpy (keystring, accelerator, 4); + keystring [4] = '\000'; + + tmp_keycode = strtol (keystring, &endptr, 16); + + if (endptr == NULL || *endptr != '\000') + { + error = TRUE; + goto out; + } + else if (accelerator_codes != NULL) + { + /* 0x00 is an invalid keycode too. */ + if (tmp_keycode == 0) + { + error = TRUE; + goto out; + } + else + { + *accelerator_codes = g_new0 (guint, 2); + (*accelerator_codes)[0] = tmp_keycode; + } + } + else + { + /* There was a keycode in the string, but + * we cannot store it, so we have an error */ + error = TRUE; + goto out; + } + } + else + { + keyval = gdk_keyval_from_name (accelerator); + if (keyval == GDK_KEY_VoidSymbol) + { + error = TRUE; + goto out; + } + } + + if (keyval && accelerator_codes != NULL) + { + GdkKeymapKey *keys; + gint n_keys, i, j; + + if (!gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), keyval, &keys, &n_keys)) + { + /* Not in keymap */ + error = TRUE; + goto out; + } + else + { + *accelerator_codes = g_new0 (guint, n_keys + 1); + + /* Prefer level-0 group-0 keys to modified keys */ + for (i = 0, j = 0; i < n_keys; ++i) + { + if (keys[i].level == 0 && keys[i].group == 0) + (*accelerator_codes)[j++] = keys[i].keycode; + } + + /* No level-0 group-0 keys? Find in the whole group-0 */ + if (j == 0) + { + for (i = 0, j = 0; i < n_keys; ++i) + { + if (keys[i].group == 0) + (*accelerator_codes)[j++] = keys[i].keycode; + } + } + + /* Still nothing? Try in other groups */ + if (j == 0) + { + for (i = 0, j = 0; i < n_keys; ++i) + (*accelerator_codes)[j++] = keys[i].keycode; + } + + if (j == 0) + { + g_free (*accelerator_codes); + *accelerator_codes = NULL; + /* Not in keymap */ + error = TRUE; + goto out; + } + g_free (keys); + } + } + accelerator += len; len -= len; } } +out: + if (error) + keyval = mods = 0; + if (accelerator_key) *accelerator_key = gdk_keyval_to_lower (keyval); if (accelerator_mods) *accelerator_mods = mods; } +/** + * gtk_accelerator_parse: + * @accelerator: string representing an accelerator + * @accelerator_key: (out) (allow-none): return location for accelerator + * keyval, or %NULL + * @accelerator_mods: (out) (allow-none): return location for accelerator + * modifier mask, %NULL + * + * Parses a string representing an accelerator. The + * format looks like "<Control>a" or "<Shift><Alt>F1" + * or "<Release>z" (the last one is for key release). + * + * The parser is fairly liberal and allows lower or upper case, + * and also abbreviations such as "<Ctl>" and "<Ctrl>". + * Key names are parsed using gdk_keyval_from_name(). For character + * keys the name is not the symbol, but the lowercase name, e.g. one + * would use "<Ctrl>minus" instead of "<Ctrl>-". + * + * If the parse fails, @accelerator_key and @accelerator_mods will + * be set to 0 (zero). + */ +void +gtk_accelerator_parse (const gchar *accelerator, + guint *accelerator_key, + GdkModifierType *accelerator_mods) +{ + gtk_accelerator_parse_with_keycode (accelerator, accelerator_key, NULL, accelerator_mods); +} + +/** + * gtk_accelerator_name_with_keycode: + * @display: (allow-none): a #GdkDisplay or %NULL to use the default display + * @accelerator_key: accelerator keyval + * @keycode: accelerator keycode + * @accelerator_mods: accelerator modifier mask + * + * Converts an accelerator keyval and modifier mask + * into a string parseable by gtk_accelerator_parse_full(), + * similarly to gtk_accelerator_name() but handling keycodes. + * This is only useful for system-level components, applications + * should use gtk_accelerator_parse() instead. + * + * Returns: a newly allocated accelerator name. + * + * Since: 3.4 + */ +gchar * +gtk_accelerator_name_with_keycode (GdkDisplay *display, + guint accelerator_key, + guint keycode, + GdkModifierType accelerator_mods) +{ + gchar *gtk_name; + + if (display == NULL) + display = gdk_display_manager_get_default_display (gdk_display_manager_get ()); + + gdk_keymap_add_virtual_modifiers (gdk_keymap_get_for_display (display), &accelerator_mods); + gtk_name = gtk_accelerator_name (accelerator_key, accelerator_mods); + + if (!accelerator_key) + { + gchar *name; + name = g_strdup_printf ("%s0x%02x", gtk_name, keycode); + g_free (gtk_name); + return name; + } + + return gtk_name; +} + /** * gtk_accelerator_name: * @accelerator_key: accelerator keyval @@ -1304,6 +1520,7 @@ gtk_accelerator_name (guint accelerator_key, GdkModifierType accelerator_mods) { static const gchar text_release[] = ""; + static const gchar text_primary[] = ""; static const gchar text_shift[] = ""; static const gchar text_control[] = ""; static const gchar text_mod1[] = ""; @@ -1314,6 +1531,7 @@ gtk_accelerator_name (guint accelerator_key, static const gchar text_meta[] = ""; static const gchar text_super[] = ""; static const gchar text_hyper[] = ""; + GdkModifierType saved_mods; guint l; gchar *keyval_name; gchar *accelerator; @@ -1324,9 +1542,15 @@ gtk_accelerator_name (guint accelerator_key, if (!keyval_name) keyval_name = ""; + saved_mods = accelerator_mods; l = 0; if (accelerator_mods & GDK_RELEASE_MASK) l += sizeof (text_release) - 1; + if (accelerator_mods & _gtk_get_primary_accel_mod ()) + { + l += sizeof (text_primary) - 1; + accelerator_mods &= ~_gtk_get_primary_accel_mod (); /* consume the default accel */ + } if (accelerator_mods & GDK_SHIFT_MASK) l += sizeof (text_shift) - 1; if (accelerator_mods & GDK_CONTROL_MASK) @@ -1351,6 +1575,7 @@ gtk_accelerator_name (guint accelerator_key, accelerator = g_new (gchar, l + 1); + accelerator_mods = saved_mods; l = 0; accelerator[l] = 0; if (accelerator_mods & GDK_RELEASE_MASK) @@ -1358,6 +1583,12 @@ gtk_accelerator_name (guint accelerator_key, strcpy (accelerator + l, text_release); l += sizeof (text_release) - 1; } + if (accelerator_mods & _gtk_get_primary_accel_mod ()) + { + strcpy (accelerator + l, text_primary); + l += sizeof (text_primary) - 1; + accelerator_mods &= ~_gtk_get_primary_accel_mod (); /* consume the default accel */ + } if (accelerator_mods & GDK_SHIFT_MASK) { strcpy (accelerator + l, text_shift); @@ -1413,6 +1644,50 @@ gtk_accelerator_name (guint accelerator_key, return accelerator; } +/** + * gtk_accelerator_get_label_with_keycode: + * @display: (allow-none): a #GdkDisplay or %NULL to use the default display + * @accelerator_key: accelerator keyval + * @keycode: accelerator keycode + * @accelerator_mods: accelerator modifier mask + * + * Converts an accelerator keyval and modifier mask + * into a (possibly translated) string that can be displayed to + * a user, similarly to gtk_accelerator_get_label(), but handling + * keycodes. + * + * This is only useful for system-level components, applications + * should use gtk_accelerator_parse() instead. + * + * Returns: a newly-allocated string representing the accelerator. + * + * Since: 3.4 + */ +gchar * +gtk_accelerator_get_label_with_keycode (GdkDisplay *display, + guint accelerator_key, + guint keycode, + GdkModifierType accelerator_mods) +{ + gchar *gtk_label; + + if (display == NULL) + display = gdk_display_manager_get_default_display (gdk_display_manager_get ()); + + gdk_keymap_add_virtual_modifiers (gdk_keymap_get_for_display (display), &accelerator_mods); + gtk_label = gtk_accelerator_get_label (accelerator_key, accelerator_mods); + + if (!accelerator_key) + { + gchar *label; + label = g_strdup_printf ("%s0x%02x", gtk_label, keycode); + g_free (gtk_label); + return label; + } + + return gtk_label; +} + /** * gtk_accelerator_get_label: * @accelerator_key: accelerator keyval @@ -1466,9 +1741,10 @@ gtk_accelerator_set_default_mod_mask (GdkModifierType default_mod_mask) /** * gtk_accelerator_get_default_mod_mask: - * @returns: the default accelerator modifier mask * * Gets the value set by gtk_accelerator_set_default_mod_mask(). + * + * Returns: the default accelerator modifier mask */ GdkModifierType gtk_accelerator_get_default_mod_mask (void)