diff options
-rw-r--r-- | demos/gtk-demo/shortcuts-builder.ui | 38 | ||||
-rw-r--r-- | gtk/gtkshortcutlabel.c | 107 | ||||
-rw-r--r-- | gtk/gtkshortcutsshortcut.c | 10 |
3 files changed, 148 insertions, 7 deletions
diff --git a/demos/gtk-demo/shortcuts-builder.ui b/demos/gtk-demo/shortcuts-builder.ui index 6b587f2e72..20ed76009a 100644 --- a/demos/gtk-demo/shortcuts-builder.ui +++ b/demos/gtk-demo/shortcuts-builder.ui @@ -502,6 +502,44 @@ </object> </child> + + <child> + <object class="GtkShortcutsGroup"> + <property name="visible">1</property> + <property name="title" translatable="yes">'Special' combinations</property> + + <child> + <object class="GtkShortcutsShortcut"> + <property name="visible">1</property> + <property name="accelerator">t+t</property> + <property name="title" translatable="yes">You want tea ?</property> + </object> + </child> + <child> + <object class="GtkShortcutsShortcut"> + <property name="visible">1</property> + <property name="accelerator"><shift><ctrl></property> + <property name="title" translatable="yes">Shift Control</property> + </object> + </child> + <child> + <object class="GtkShortcutsShortcut"> + <property name="visible">1</property> + <property name="accelerator"><ctrl>&<ctrl></property> + <property name="title" translatable="yes">Control Control</property> + </object> + </child> + <child> + <object class="GtkShortcutsShortcut"> + <property name="visible">1</property> + <property name="accelerator">Control_L&Control_R</property> + <property name="title" translatable="yes">Left and right control</property> + </object> + </child> + + </object> + </child> + </object> </child> </object> diff --git a/gtk/gtkshortcutlabel.c b/gtk/gtkshortcutlabel.c index 24c4f1b5f3..ef7d462822 100644 --- a/gtk/gtkshortcutlabel.c +++ b/gtk/gtkshortcutlabel.c @@ -46,14 +46,71 @@ enum { static GParamSpec *properties[LAST_PROP]; +static gchar * +get_modifier_label (guint key) +{ + const gchar *subscript; + const gchar *label; + + switch (key) + { + case GDK_KEY_Shift_L: + case GDK_KEY_Control_L: + case GDK_KEY_Alt_L: + case GDK_KEY_Meta_L: + case GDK_KEY_Super_L: + case GDK_KEY_Hyper_L: + subscript = "L"; + break; + case GDK_KEY_Shift_R: + case GDK_KEY_Control_R: + case GDK_KEY_Alt_R: + case GDK_KEY_Meta_R: + case GDK_KEY_Super_R: + case GDK_KEY_Hyper_R: + subscript = "R"; + break; + default: + g_assert_not_reached (); + } + + switch (key) + { + case GDK_KEY_Shift_L: case GDK_KEY_Shift_R: + label = C_("keyboard label", "Shift"); + break; + case GDK_KEY_Control_L: case GDK_KEY_Control_R: + label = C_("keyboard label", "Ctrl"); + break; + case GDK_KEY_Alt_L: case GDK_KEY_Alt_R: + label = C_("keyboard label", "Alt"); + break; + case GDK_KEY_Meta_L: case GDK_KEY_Meta_R: + label = C_("keyboard label", "Meta"); + break; + case GDK_KEY_Super_L: case GDK_KEY_Super_R: + label = C_("keyboard label", "Super"); + break; + case GDK_KEY_Hyper_L: case GDK_KEY_Hyper_R: + label = C_("keyboard label", "Hyper"); + break; + default: + g_assert_not_reached (); + } + + return g_strdup_printf ("%s<sub>%s</sub>", label, subscript); +} + static gchar ** get_labels (guint key, GdkModifierType modifier, guint *n_mods) { const gchar *labels[16]; + GList *freeme = NULL; gchar key_label[6]; gchar *tmp; gunichar ch; gint i = 0; + gchar **retval; if (modifier & GDK_SHIFT_MASK) labels[i++] = C_("keyboard label", "Shift"); @@ -97,6 +154,15 @@ get_labels (guint key, GdkModifierType modifier, guint *n_mods) { switch (key) { + case GDK_KEY_Shift_L: case GDK_KEY_Shift_R: + case GDK_KEY_Control_L: case GDK_KEY_Control_R: + case GDK_KEY_Alt_L: case GDK_KEY_Alt_R: + case GDK_KEY_Meta_L: case GDK_KEY_Meta_R: + case GDK_KEY_Super_L: case GDK_KEY_Super_R: + case GDK_KEY_Hyper_L: case GDK_KEY_Hyper_R: + freeme = g_list_prepend (freeme, get_modifier_label (key)); + labels[i++] = (const gchar*)freeme->data; + break; case GDK_KEY_Left: labels[i++] = "\xe2\x86\x90"; break; @@ -141,7 +207,11 @@ get_labels (guint key, GdkModifierType modifier, guint *n_mods) labels[i] = NULL; - return g_strdupv ((gchar **)labels); + retval = g_strdupv ((gchar **)labels); + + g_list_free_full (freeme, g_free); + + return retval; } static GtkWidget * @@ -184,6 +254,8 @@ display_shortcut (GtkContainer *self, gtk_widget_set_size_request (frame, 50, -1); disp = gtk_label_new (keys[i]); + gtk_label_set_use_markup (GTK_LABEL (disp), TRUE); + gtk_widget_show (disp); gtk_container_add (GTK_CONTAINER (frame), disp); } @@ -191,8 +263,8 @@ display_shortcut (GtkContainer *self, } static gboolean -parse_sequence (GtkShortcutLabel *self, - const gchar *str) +parse_combination (GtkShortcutLabel *self, + const gchar *str) { gchar **accels; gint k; @@ -200,7 +272,7 @@ parse_sequence (GtkShortcutLabel *self, guint key = 0; gboolean retval = TRUE; - accels = g_strsplit (str, "+", 0); + accels = g_strsplit (str, "&", 0); for (k = 0; accels[k]; k++) { gtk_accelerator_parse (accels[k], &key, &modifier); @@ -209,6 +281,9 @@ parse_sequence (GtkShortcutLabel *self, retval = FALSE; break; } + if (k > 0) + gtk_container_add (GTK_CONTAINER (self), dim_label ("+")); + display_shortcut (GTK_CONTAINER (self), key, modifier); } g_strfreev (accels); @@ -217,6 +292,29 @@ parse_sequence (GtkShortcutLabel *self, } static gboolean +parse_sequence (GtkShortcutLabel *self, + const gchar *str) +{ + gchar **accels; + gint k; + gboolean retval = TRUE; + + accels = g_strsplit (str, "+", 0); + for (k = 0; accels[k]; k++) + { + if (!parse_combination (self, accels[k])) + { + retval = FALSE; + break; + } + } + + g_strfreev (accels); + + return retval; +} + +static gboolean parse_range (GtkShortcutLabel *self, const gchar *str) { @@ -231,6 +329,7 @@ parse_range (GtkShortcutLabel *self, return FALSE; gtk_container_add (GTK_CONTAINER (self), dim_label ("⋯")); + if (!parse_sequence (self, dots + 3)) return FALSE; diff --git a/gtk/gtkshortcutsshortcut.c b/gtk/gtkshortcutsshortcut.c index 28aab42a8d..af5515dce7 100644 --- a/gtk/gtkshortcutsshortcut.c +++ b/gtk/gtkshortcutsshortcut.c @@ -464,15 +464,19 @@ gtk_shortcuts_shortcut_class_init (GtkShortcutsShortcutClass *klass) * gtk_accelerator_parse(). Multiple accelerators can be specified by separating * them with a space, but keep in mind that the available width is limited. * It is also possible to specify ranges of shortcuts, using ... between the keys. - * Sequences of keys can be specified using a + between the keys. + * Sequences of keys can be specified using a + or & between the keys. * * Examples: * - A single shortcut: <ctl><alt>delete * - Two alternative shortcuts: <shift>a Home * - A range of shortcuts: <alt>1...<alt>9 - * - A sequence of key combinations: <ctl>c+<ctl>x + * - Several keys pressed together: Control_L&Control_R + * - A sequence of shortcuts or keys: <ctl>c+<ctl>x * - * Note that < and > need to be escaped as < and > when used + * Use + instead of & when the keys may (or have to be) pressed sequentially (e.g + * use t+t for 'press the t key twice'). + * + * Note that <, > and & need to be escaped as <, > and & when used * in .ui files. */ properties[PROP_ACCELERATOR] = |