diff options
Diffstat (limited to 'panels/keyboard/cc-alt-chars-key-dialog.c')
-rw-r--r-- | panels/keyboard/cc-alt-chars-key-dialog.c | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/panels/keyboard/cc-alt-chars-key-dialog.c b/panels/keyboard/cc-alt-chars-key-dialog.c new file mode 100644 index 0000000..c32c6ba --- /dev/null +++ b/panels/keyboard/cc-alt-chars-key-dialog.c @@ -0,0 +1,209 @@ +/* cc-alt-chars-key-dialog.c + * + * Copyright 2019 Bastien Nocera <hadess@hadess.net> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "cc-alt-chars-key-dialog.h" + +struct _CcAltCharsKeyDialog +{ + GtkDialog parent_instance; + + GSettings *input_source_settings; + + GtkRadioButton *leftalt_radio; + GtkRadioButton *leftsuper_radio; + GtkRadioButton *menukey_radio; + GtkRadioButton *rightalt_radio; + GtkRadioButton *rightctrl_radio; + GtkRadioButton *rightsuper_radio; +}; + +G_DEFINE_TYPE (CcAltCharsKeyDialog, cc_alt_chars_key_dialog, GTK_TYPE_DIALOG) + +static GtkRadioButton * +get_radio_button_from_xkb_option_name (CcAltCharsKeyDialog *self, + const gchar *name) +{ + if (g_str_equal (name, "lv3:switch")) + return self->rightctrl_radio; + else if (g_str_equal (name, "lv3:menu_switch")) + return self->menukey_radio; + else if (g_str_equal (name, "lv3:lwin_switch")) + return self->leftsuper_radio; + else if (g_str_equal (name, "lv3:rwin_switch")) + return self->rightsuper_radio; + else if (g_str_equal (name, "lv3:lalt_switch")) + return self->leftalt_radio; + else if (g_str_equal (name, "lv3:ralt_switch")) + return self->rightalt_radio; + + return NULL; +} + +static const gchar * +get_xkb_option_name_from_radio_button (CcAltCharsKeyDialog *self, + GtkRadioButton *radio) +{ + if (radio == self->rightctrl_radio) + return "lv3:switch"; + else if (radio == self->menukey_radio) + return "lv3:menu_switch"; + else if (radio == self->leftsuper_radio) + return "lv3:lwin_switch"; + else if (radio == self->rightsuper_radio) + return "lv3:rwin_switch"; + else if (radio == self->leftalt_radio) + return "lv3:lalt_switch"; + else if (radio == self->rightalt_radio) + return "lv3:ralt_switch"; + + return NULL; +} + +static void +update_active_radio (CcAltCharsKeyDialog *self) +{ + g_auto(GStrv) options = NULL; + guint i; + + options = g_settings_get_strv (self->input_source_settings, "xkb-options"); + + for (i = 0; options != NULL && options[i] != NULL; i++) + { + GtkRadioButton *radio; + + if (!g_str_has_prefix (options[i], "lv3:")) + continue; + + radio = get_radio_button_from_xkb_option_name (self, options[i]); + + if (!radio) + continue; + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE); + return; + } + + /* Fallback to Right Alt as default */ + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->rightalt_radio), TRUE); +} + +static void +on_active_lv3_changed_cb (GtkRadioButton *radio, + CcAltCharsKeyDialog *self) +{ + g_autoptr(GPtrArray) array = NULL; + g_auto(GStrv) options = NULL; + gboolean found; + guint i; + + if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio))) + return; + + /* Either replace the existing "lv3:" option in the string + * array, or add the option at the end + */ + array = g_ptr_array_new (); + options = g_settings_get_strv (self->input_source_settings, "xkb-options"); + found = FALSE; + + for (i = 0; options != NULL && options[i] != NULL; i++) + { + if (g_str_has_prefix (options[i], "lv3:")) + { + g_ptr_array_add (array, (gchar *)get_xkb_option_name_from_radio_button (self, radio)); + found = TRUE; + } + else + { + g_ptr_array_add (array, options[i]); + } + } + + if (!found) + g_ptr_array_add (array, (gchar *)get_xkb_option_name_from_radio_button (self, radio)); + + g_ptr_array_add (array, NULL); + + g_settings_set_strv (self->input_source_settings, + "xkb-options", + (const gchar * const *) array->pdata); +} + +static void +on_xkb_options_changed_cb (CcAltCharsKeyDialog *self) +{ + update_active_radio (self); +} + +static void +cc_alt_chars_key_dialog_finalize (GObject *object) +{ + CcAltCharsKeyDialog *self = (CcAltCharsKeyDialog *)object; + + g_clear_object (&self->input_source_settings); + + G_OBJECT_CLASS (cc_alt_chars_key_dialog_parent_class)->finalize (object); +} + +static void +cc_alt_chars_key_dialog_class_init (CcAltCharsKeyDialogClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = cc_alt_chars_key_dialog_finalize; + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/keyboard/cc-alt-chars-key-dialog.ui"); + + gtk_widget_class_bind_template_child (widget_class, CcAltCharsKeyDialog, leftalt_radio); + gtk_widget_class_bind_template_child (widget_class, CcAltCharsKeyDialog, leftsuper_radio); + gtk_widget_class_bind_template_child (widget_class, CcAltCharsKeyDialog, menukey_radio); + gtk_widget_class_bind_template_child (widget_class, CcAltCharsKeyDialog, rightalt_radio); + gtk_widget_class_bind_template_child (widget_class, CcAltCharsKeyDialog, rightctrl_radio); + gtk_widget_class_bind_template_child (widget_class, CcAltCharsKeyDialog, rightsuper_radio); + + gtk_widget_class_bind_template_callback (widget_class, on_active_lv3_changed_cb); +} + +static void +cc_alt_chars_key_dialog_init (CcAltCharsKeyDialog *self) +{ + gtk_widget_init_template (GTK_WIDGET (self)); + + self->input_source_settings = g_settings_new ("org.gnome.desktop.input-sources"); + g_signal_connect_object (self->input_source_settings, + "changed::xkb-options", + G_CALLBACK (on_xkb_options_changed_cb), + self, G_CONNECT_SWAPPED); + update_active_radio (self); +} + +CcAltCharsKeyDialog * +cc_alt_chars_key_dialog_new (GSettings *input_settings) +{ + CcAltCharsKeyDialog *self; + + self = g_object_new (CC_TYPE_ALT_CHARS_KEY_DIALOG, + "use-header-bar", 1, + NULL); + self->input_source_settings = g_object_ref (input_settings); + + return self; +} |