From 82504848ed9a2345d5af8cd45c0f8d4182984bb1 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Tue, 8 Dec 2020 12:06:56 -0800 Subject: [PATCH 1/3] keyboard: Allow disabling alternate characters key Support for toggling a binding was added to accommodate the compose key. At the time, I avoided changing the behavior of the alternate characters key. But it seems good to change this, which should resolve https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/918 --- panels/keyboard/cc-keyboard-panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panels/keyboard/cc-keyboard-panel.c b/panels/keyboard/cc-keyboard-panel.c index 8c0e030561..7ba51e1261 100644 --- a/panels/keyboard/cc-keyboard-panel.c +++ b/panels/keyboard/cc-keyboard-panel.c @@ -76,7 +76,7 @@ static const CcXkbModifier LV3_MODIFIER = { { NC_("keyboard key", "Right Ctrl"), "lv3:switch" }, { NULL, NULL } }, - "lv3:ralt_switch", + NULL, }; static const CcXkbModifier COMPOSE_MODIFIER = { -- GitLab From 17f6949574a880d486db56be6c81053c0c32e0d3 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 28 Dec 2020 13:25:50 -0800 Subject: [PATCH 2/3] keyboard: For xkb options, have "Layout default" toggle, and "None" Meant to address issues mentioned in https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1214 using the solution proposed there. There is no "None" option for the compose key, since there doesn't appear to be a way to disable it on the unusual layouts where it's available by default. XKB options are a mess, but this seems like a more accurate representation of how they function. --- panels/keyboard/cc-keyboard-panel.c | 5 +- panels/keyboard/cc-xkb-modifier-dialog.c | 78 +++++++++++++---------- panels/keyboard/cc-xkb-modifier-dialog.h | 1 + panels/keyboard/cc-xkb-modifier-dialog.ui | 5 +- 4 files changed, 52 insertions(+), 37 deletions(-) diff --git a/panels/keyboard/cc-keyboard-panel.c b/panels/keyboard/cc-keyboard-panel.c index 7ba51e1261..f1dfc425ee 100644 --- a/panels/keyboard/cc-keyboard-panel.c +++ b/panels/keyboard/cc-keyboard-panel.c @@ -68,6 +68,7 @@ static const CcXkbModifier LV3_MODIFIER = { N_("Alternate Characters Key"), N_("The alternate characters key can be used to enter additional characters. These are sometimes printed as a third-option on your keyboard."), (CcXkbOption[]){ + { NC_("keyboard key", "None"), "lv3:ralt_alt" }, { NC_("keyboard key", "Left Alt"), "lv3:lalt_switch" }, { NC_("keyboard key", "Right Alt"), "lv3:ralt_switch" }, { NC_("keyboard key", "Left Super"), "lv3:lwin_switch" }, @@ -76,7 +77,8 @@ static const CcXkbModifier LV3_MODIFIER = { { NC_("keyboard key", "Right Ctrl"), "lv3:switch" }, { NULL, NULL } }, - NULL, + "lv3:ralt_switch", + "lv3:ralt_alt", }; static const CcXkbModifier COMPOSE_MODIFIER = { @@ -98,6 +100,7 @@ static const CcXkbModifier COMPOSE_MODIFIER = { { NULL, NULL } }, NULL, + NULL, }; static const gchar *custom_css = diff --git a/panels/keyboard/cc-xkb-modifier-dialog.c b/panels/keyboard/cc-xkb-modifier-dialog.c index b1fae3d6d2..dc5a91e449 100644 --- a/panels/keyboard/cc-xkb-modifier-dialog.c +++ b/panels/keyboard/cc-xkb-modifier-dialog.c @@ -30,7 +30,7 @@ struct _CcXkbModifierDialog GtkDialog parent_instance; GtkLabel *description_label; - GtkSwitch *enabled_switch; + GtkSwitch *default_switch; GtkListBox *listbox; GtkListBox *switch_listbox; HdyActionRow *switch_row; @@ -53,9 +53,9 @@ get_xkb_option_from_name (const CcXkbModifier *modifier, const gchar* name) const CcXkbOption *options = modifier->options; int i; - for (i = 0; options[i].label && options[i].xkb_option; i++) + for (i = 0; options[i].label; i++) { - if (g_str_equal (name, options[i].xkb_option)) + if (g_strcmp0 (name, options[i].xkb_option) == 0) return &options[i]; } @@ -83,9 +83,9 @@ static void update_active_radio (CcXkbModifierDialog *self) { g_auto(GStrv) options = NULL; - GtkRadioButton *rightalt_radio; - const CcXkbOption *default_option; + GtkRadioButton *none_radio; guint i; + gboolean have_nodefault_option = FALSE; options = g_settings_get_strv (self->input_source_settings, "xkb-options"); @@ -96,26 +96,28 @@ update_active_radio (CcXkbModifierDialog *self) if (!g_str_has_prefix (options[i], self->modifier->prefix)) continue; + if (g_strcmp0 (options[i], self->modifier->nodefault_option) == 0) + have_nodefault_option = TRUE; + radio = get_radio_button_from_xkb_option_name (self, options[i]); if (!radio) continue; gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE); - gtk_switch_set_active (self->enabled_switch, TRUE); + gtk_switch_set_active (self->default_switch, FALSE); return; } - if (self->modifier->default_option != NULL) + if (have_nodefault_option) { - default_option = get_xkb_option_from_name(self->modifier, self->modifier->default_option); - rightalt_radio = get_radio_button_from_xkb_option_name (self, default_option->xkb_option); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rightalt_radio), TRUE); - gtk_switch_set_active (self->enabled_switch, TRUE); + none_radio = get_radio_button_from_xkb_option_name (self, self->modifier->nodefault_option); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (none_radio), TRUE); + gtk_switch_set_active (self->default_switch, FALSE); } else { - gtk_switch_set_active (self->enabled_switch, FALSE); + gtk_switch_set_active (self->default_switch, TRUE); } } @@ -127,6 +129,12 @@ set_xkb_option (CcXkbModifierDialog *self, g_auto(GStrv) options = NULL; gboolean found; guint i; + gboolean add_nodefault; + + add_nodefault = xkb_option != self->modifier->default_option + && xkb_option != self->modifier->nodefault_option + && xkb_option != NULL + && self->modifier->nodefault_option != NULL; /* Either replace the existing ":" option in the string * array, or add the option at the end @@ -139,6 +147,8 @@ set_xkb_option (CcXkbModifierDialog *self, { if (g_str_has_prefix (options[i], self->modifier->prefix)) { + if (!found && add_nodefault) + g_ptr_array_add (array, self->modifier->nodefault_option); if (!found && xkb_option != NULL) g_ptr_array_add (array, xkb_option); found = TRUE; @@ -149,6 +159,8 @@ set_xkb_option (CcXkbModifierDialog *self, } } + if (!found && add_nodefault) + g_ptr_array_add (array, self->modifier->nodefault_option); if (!found && xkb_option != NULL) g_ptr_array_add (array, xkb_option); @@ -168,7 +180,7 @@ on_active_radio_changed_cb (CcXkbModifierDialog *self, if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio))) return; - if (!gtk_switch_get_state (self->enabled_switch)) + if (gtk_switch_get_state (self->default_switch)) return; xkb_option = (gchar *)g_object_get_data (G_OBJECT (radio), "xkb-option"); @@ -183,17 +195,17 @@ on_xkb_options_changed_cb (CcXkbModifierDialog *self) } static gboolean -enable_switch_changed_cb (GtkSwitch *widget, - gboolean state, - gpointer user_data) +default_switch_changed_cb (GtkSwitch *widget, + gboolean state, + gpointer user_data) { CcXkbModifierDialog *self = user_data; gchar *xkb_option; GSList *l; - gtk_widget_set_sensitive (GTK_WIDGET (self->listbox), state); + gtk_widget_set_sensitive (GTK_WIDGET (self->listbox), !state); - if (state) + if (!state) { for (l = self->radio_group; l != NULL; l = l->next) { @@ -234,12 +246,12 @@ cc_xkb_modifier_dialog_class_init (CcXkbModifierDialogClass *klass) gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/keyboard/cc-xkb-modifier-dialog.ui"); gtk_widget_class_bind_template_child (widget_class, CcXkbModifierDialog, description_label); - gtk_widget_class_bind_template_child (widget_class, CcXkbModifierDialog, enabled_switch); + gtk_widget_class_bind_template_child (widget_class, CcXkbModifierDialog, default_switch); gtk_widget_class_bind_template_child (widget_class, CcXkbModifierDialog, listbox); gtk_widget_class_bind_template_child (widget_class, CcXkbModifierDialog, switch_listbox); gtk_widget_class_bind_template_child (widget_class, CcXkbModifierDialog, switch_row); - gtk_widget_class_bind_template_callback (widget_class, enable_switch_changed_cb); + gtk_widget_class_bind_template_callback (widget_class, default_switch_changed_cb); } static void @@ -249,7 +261,7 @@ add_radio_buttons (CcXkbModifierDialog *self) CcXkbOption *options = self->modifier->options; int i; - for (i = 0; options[i].label && options[i].xkb_option; i++) + for (i = 0; options[i].label != NULL; i++) { row = g_object_new (GTK_TYPE_LIST_BOX_ROW, "visible", TRUE, @@ -319,12 +331,10 @@ cc_xkb_modifier_dialog_new (GSettings *input_settings, self->modifier = modifier; gtk_window_set_title (GTK_WINDOW (self), gettext (modifier->title)); - hdy_preferences_row_set_title (HDY_PREFERENCES_ROW (self->switch_row), gettext (modifier->title)); gtk_label_set_markup (self->description_label, gettext (modifier->description)); - gtk_widget_set_visible (GTK_WIDGET (self->switch_listbox), modifier->default_option == NULL); add_radio_buttons (self); update_active_radio (self); - gtk_widget_set_sensitive (GTK_WIDGET (self->listbox), gtk_switch_get_state (self->enabled_switch)); + gtk_widget_set_sensitive (GTK_WIDGET (self->listbox), !gtk_switch_get_state (self->default_switch)); return self; } @@ -338,6 +348,7 @@ xcb_modifier_transform_binding_to_label (GValue *value, const CcXkbOption *entry = NULL; const char **items; guint i; + gboolean have_nodefault_option = FALSE; items = g_variant_get_strv (variant, NULL); @@ -346,19 +357,18 @@ xcb_modifier_transform_binding_to_label (GValue *value, entry = get_xkb_option_from_name (modifier, items[i]); if (entry != NULL) break; - } - if (entry == NULL && modifier->default_option == NULL) - { - g_value_set_string (value, _("Disabled")); - return TRUE; + if (g_strcmp0 (items[i], modifier->nodefault_option) == 0) + have_nodefault_option = TRUE; } + + if (entry != NULL) + g_value_set_string (value, + g_dpgettext2 (NULL, "keyboard key", entry->label)); + if (entry == NULL && have_nodefault_option) + g_value_set_string (value, _("None")); else if (entry == NULL) - { - entry = get_xkb_option_from_name(modifier, modifier->default_option); - } + g_value_set_string (value, _("Layout default")); - g_value_set_string (value, - g_dpgettext2 (NULL, "keyboard key", entry->label)); return TRUE; } diff --git a/panels/keyboard/cc-xkb-modifier-dialog.h b/panels/keyboard/cc-xkb-modifier-dialog.h index 91efbcdde7..fd05b329bb 100644 --- a/panels/keyboard/cc-xkb-modifier-dialog.h +++ b/panels/keyboard/cc-xkb-modifier-dialog.h @@ -37,6 +37,7 @@ typedef struct gchar *description; CcXkbOption *options; gchar *default_option; + gchar *nodefault_option; } CcXkbModifier; #define CC_TYPE_XKB_MODIFIER_DIALOG (cc_xkb_modifier_dialog_get_type()) diff --git a/panels/keyboard/cc-xkb-modifier-dialog.ui b/panels/keyboard/cc-xkb-modifier-dialog.ui index 7863ebef31..e8e030de96 100644 --- a/panels/keyboard/cc-xkb-modifier-dialog.ui +++ b/panels/keyboard/cc-xkb-modifier-dialog.ui @@ -43,11 +43,12 @@ True False False + Use layout default - + True center - + -- GitLab From 1070b1c2a1669ae9fe2c703a95fd2bc7f4c05398 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 16 Aug 2021 13:56:05 -0700 Subject: [PATCH 3/3] keyboard: Avoid modifying `xkb-options` when user changes nothing Avoids clobbering certain custom settings that can't be set in UI. --- panels/keyboard/cc-xkb-modifier-dialog.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/panels/keyboard/cc-xkb-modifier-dialog.c b/panels/keyboard/cc-xkb-modifier-dialog.c index dc5a91e449..16b89a435d 100644 --- a/panels/keyboard/cc-xkb-modifier-dialog.c +++ b/panels/keyboard/cc-xkb-modifier-dialog.c @@ -38,6 +38,7 @@ struct _CcXkbModifierDialog GSettings *input_source_settings; const CcXkbModifier *modifier; GSList *radio_group; + gboolean updating_active_radio; }; G_DEFINE_TYPE (CcXkbModifierDialog, cc_xkb_modifier_dialog, GTK_TYPE_DIALOG) @@ -87,6 +88,9 @@ update_active_radio (CcXkbModifierDialog *self) guint i; gboolean have_nodefault_option = FALSE; + // Block `on_active_radio_changed_cb` from running + self->updating_active_radio = TRUE; + options = g_settings_get_strv (self->input_source_settings, "xkb-options"); for (i = 0; options != NULL && options[i] != NULL; i++) @@ -106,6 +110,7 @@ update_active_radio (CcXkbModifierDialog *self) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE); gtk_switch_set_active (self->default_switch, FALSE); + self->updating_active_radio = FALSE; return; } @@ -119,6 +124,8 @@ update_active_radio (CcXkbModifierDialog *self) { gtk_switch_set_active (self->default_switch, TRUE); } + + self->updating_active_radio = FALSE; } static void @@ -183,6 +190,9 @@ on_active_radio_changed_cb (CcXkbModifierDialog *self, if (gtk_switch_get_state (self->default_switch)) return; + if (self->updating_active_radio) + return; + xkb_option = (gchar *)g_object_get_data (G_OBJECT (radio), "xkb-option"); set_xkb_option (self, xkb_option); } -- GitLab