[gnome-control-center/wip/alt-chars-key: 2/2] keyboard: Add "Alternate Characters Key" configuration



commit 2e99dd4f5e7924ae99251659977c9d0abfb8159b
Author: Bastien Nocera <hadess hadess net>
Date:   Thu Mar 29 13:33:15 2018 +0200

    keyboard: Add "Alternate Characters Key" configuration
    
    This adds an entry to select the "Level 3" selection key, which is
    usually Right Alt (or Alt-Gr on a majority of keyboards).
    Mockups at [1].
    
    However, we replaced the "Left Ctrl" key option with a "Menu key"
    option, as "Left Ctrl" isn't a possible XKB option for the level3 key.
    
    [1] 
https://raw.githubusercontent.com/gnome-design-team/gnome-mockups/master/system-settings/keyboard/keyboard-wires.png

 panels/keyboard/cc-alt-chars-key-dialog.c  | 213 +++++++++++++++++++++++++++++
 panels/keyboard/cc-alt-chars-key-dialog.h  |  32 +++++
 panels/keyboard/cc-alt-chars-key-dialog.ui | 155 +++++++++++++++++++++
 panels/keyboard/cc-keyboard-panel.c        |  89 +++++++++++-
 panels/keyboard/cc-keyboard-panel.ui       |  31 +++++
 panels/keyboard/keyboard.gresource.xml     |   1 +
 panels/keyboard/meson.build                |   1 +
 7 files changed, 521 insertions(+), 1 deletion(-)
---
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 000000000..3cce824f8
--- /dev/null
+++ b/panels/keyboard/cc-alt-chars-key-dialog.c
@@ -0,0 +1,213 @@
+/* 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;
+
+      g_message ("Found radio for %s", options[i]);
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE);
+      return;
+    }
+
+  /* Fallback to Right Alt as default */
+  g_message ("Using fallback");
+  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 (GSettings           *settings,
+                           const gchar         *key,
+                           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 (self->input_source_settings,
+                    "changed::xkb-options",
+                    G_CALLBACK (on_xkb_options_changed_cb),
+                    self);
+  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;
+}
diff --git a/panels/keyboard/cc-alt-chars-key-dialog.h b/panels/keyboard/cc-alt-chars-key-dialog.h
new file mode 100644
index 000000000..fb0c85357
--- /dev/null
+++ b/panels/keyboard/cc-alt-chars-key-dialog.h
@@ -0,0 +1,32 @@
+/* cc-alt-chars-key-dialog.h
+ *
+ * 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
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_ALT_CHARS_KEY_DIALOG (cc_alt_chars_key_dialog_get_type())
+G_DECLARE_FINAL_TYPE (CcAltCharsKeyDialog, cc_alt_chars_key_dialog, CC, ALT_CHARS_KEY_DIALOG, GtkDialog)
+
+CcAltCharsKeyDialog *cc_alt_chars_key_dialog_new (GSettings *input_settings);
+
+G_END_DECLS
diff --git a/panels/keyboard/cc-alt-chars-key-dialog.ui b/panels/keyboard/cc-alt-chars-key-dialog.ui
new file mode 100644
index 000000000..67d720611
--- /dev/null
+++ b/panels/keyboard/cc-alt-chars-key-dialog.ui
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="CcAltCharsKeyDialog" parent="GtkDialog">
+    <property name="modal">True</property>
+    <property name="can_focus">False</property>
+    <property name="resizable">False</property>
+    <property name="type_hint">dialog</property>
+    <property name="title" translatable="yes">Alternate Characters Key</property>
+    <signal name="delete-event" handler="gtk_widget_hide_on_delete" />
+    <child internal-child="vbox">
+      <object class="GtkBox">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin">18</property>
+            <property name="orientation">vertical</property>
+
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_top">6</property>
+                <property name="margin_bottom">12</property>
+                <property name="label" translatable="yes">The alternate characters key can be used to enter 
additional characters. These are sometimes printed as a third-option on your keyboard.</property>
+                <property name="wrap">True</property>
+                <property name="width_chars">40</property>
+                <property name="max_width_chars">40</property>
+              </object>
+            </child>
+
+            <child>
+              <object class="GtkGrid">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="row_spacing">6</property>
+                <property name="column_spacing">6</property>
+                <property name="column_homogeneous">True</property>
+
+                <child>
+                  <object class="GtkRadioButton" id="leftalt_radio">
+                    <property name="label" translatable="yes">Left Alt</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="active">True</property>
+                    <property name="draw_indicator">True</property>
+                    <signal name="toggled" handler="on_active_lv3_changed_cb" object="CcAltCharsKeyDialog" 
swapped="no" />
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">0</property>
+                  </packing>
+                </child>
+
+                <child>
+                  <object class="GtkRadioButton" id="rightalt_radio">
+                    <property name="label" translatable="yes">Right Alt</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="draw_indicator">True</property>
+                    <property name="group">leftalt_radio</property>
+                    <signal name="toggled" handler="on_active_lv3_changed_cb" object="CcAltCharsKeyDialog" 
swapped="no" />
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">0</property>
+                  </packing>
+                </child>
+
+                <child>
+                  <object class="GtkRadioButton" id="leftsuper_radio">
+                    <property name="label" translatable="yes">Left Super</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="draw_indicator">True</property>
+                    <property name="group">leftalt_radio</property>
+                    <signal name="toggled" handler="on_active_lv3_changed_cb" object="CcAltCharsKeyDialog" 
swapped="no" />
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">1</property>
+                  </packing>
+                </child>
+
+                <child>
+                  <object class="GtkRadioButton" id="rightsuper_radio">
+                    <property name="label" translatable="yes">Right Super</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="draw_indicator">True</property>
+                    <property name="group">leftalt_radio</property>
+                    <signal name="toggled" handler="on_active_lv3_changed_cb" object="CcAltCharsKeyDialog" 
swapped="no" />
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">1</property>
+                  </packing>
+                </child>
+
+                <child>
+                  <object class="GtkRadioButton" id="menukey_radio">
+                    <property name="label" translatable="yes">Menu key</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="draw_indicator">True</property>
+                    <property name="group">leftalt_radio</property>
+                    <signal name="toggled" handler="on_active_lv3_changed_cb" object="CcAltCharsKeyDialog" 
swapped="no" />
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">2</property>
+                  </packing>
+                </child>
+
+                <child>
+                  <object class="GtkRadioButton" id="rightctrl_radio">
+                    <property name="label" translatable="yes">Right Ctrl</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="draw_indicator">True</property>
+                    <property name="group">leftalt_radio</property>
+                    <signal name="toggled" handler="on_active_lv3_changed_cb" object="CcAltCharsKeyDialog" 
swapped="no" />
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">2</property>
+                  </packing>
+                </child>
+
+              </object>
+            </child>
+
+          </object>
+        </child>
+
+      </object>
+    </child>
+
+    <child internal-child="headerbar">
+      <object class="GtkHeaderBar">
+        <property name="can_focus">False</property>
+        <property name="show_close_button">True</property>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/panels/keyboard/cc-keyboard-panel.c b/panels/keyboard/cc-keyboard-panel.c
index 3d647cb85..8ff8f840c 100644
--- a/panels/keyboard/cc-keyboard-panel.c
+++ b/panels/keyboard/cc-keyboard-panel.c
@@ -22,6 +22,7 @@
 
 #include <glib/gi18n.h>
 
+#include "cc-alt-chars-key-dialog.h"
 #include "cc-keyboard-item.h"
 #include "cc-keyboard-manager.h"
 #include "cc-keyboard-option.h"
@@ -58,6 +59,11 @@ struct _CcKeyboardPanel
   GtkListBoxRow      *add_shortcut_row;
   GtkSizeGroup       *accelerator_sizegroup;
 
+  /* Alternate characters key */
+  CcAltCharsKeyDialog *alt_chars_key_dialog;
+  GSettings           *input_source_settings;
+  GtkWidget           *value_alternate_chars;
+
   /* Custom shortcut dialog */
   GtkWidget          *shortcut_editor;
 
@@ -78,6 +84,21 @@ static const gchar* custom_css =
 "    padding: 0;"
 "}";
 
+
+#define DEFAULT_LV3_OPTION 5
+static struct {
+  const char *xkb_option;
+  const char *label;
+  const char *widget_name;
+} lv3_xkb_options[] = {
+  { "lv3:switch", NC_("keyboard key", "Right Ctrl"), "radiobutton_rightctrl" },
+  { "lv3:menu_switch", NC_("keyboard key", "Menu Key"), "radiobutton_menukey" },
+  { "lv3:lwin_switch", NC_("keyboard key", "Left Super"), "radiobutton_leftsuper" },
+  { "lv3:rwin_switch", NC_("keyboard key", "Right Super"), "radiobutton_rightsuper" },
+  { "lv3:lalt_switch", NC_("keyboard key", "Left Alt"), "radiobutton_leftalt" },
+  { "lv3:ralt_switch", NC_("keyboard key", "Right Alt"), "radiobutton_rightalt" },
+};
+
 /* RowData functions */
 static RowData *
 row_data_new (CcKeyboardItem *item,
@@ -265,7 +286,7 @@ add_item (CcKeyboardPanel *self,
                                "binding",
                                label,
                               "label",
-                               G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE,
+                               G_SETTINGS_BIND_GET | G_BINDING_SYNC_CREATE,
                                transform_binding_to_accel,
                                NULL, NULL, NULL);
 
@@ -599,6 +620,55 @@ shortcut_row_activated (GtkWidget       *button,
   gtk_widget_show (self->shortcut_editor);
 }
 
+static void
+alternate_chars_activated (GtkWidget       *button,
+                           GtkListBoxRow   *row,
+                           CcKeyboardPanel *self)
+{
+  GtkWindow *window;
+
+  window = GTK_WINDOW (cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (self))));
+
+  gtk_window_set_transient_for (GTK_WINDOW (self->alt_chars_key_dialog), window);
+  gtk_widget_show (GTK_WIDGET (self->alt_chars_key_dialog));
+}
+
+static gboolean
+transform_binding_to_alt_chars (GValue   *value,
+                                GVariant *variant,
+                                gpointer  user_data)
+{
+  const char **items;
+  guint i;
+
+  items = g_variant_get_strv (variant, NULL);
+  if (!items)
+    goto bail;
+
+  for (i = 0; items[i] != NULL; i++)
+    {
+      guint j;
+
+      if (!g_str_has_prefix (items[i], "lv3:"))
+        continue;
+
+      for (j = 0; j < G_N_ELEMENTS (lv3_xkb_options); j++)
+        {
+          if (!g_str_equal (items[i], lv3_xkb_options[j].xkb_option))
+            continue;
+
+          g_value_set_string (value,
+                              g_dpgettext2 (NULL, "keyboard key", lv3_xkb_options[j].label));
+          return TRUE;
+        }
+    }
+
+bail:
+  g_value_set_string (value,
+                      g_dpgettext2 (NULL, "keyboard key", lv3_xkb_options[DEFAULT_LV3_OPTION].label));
+  return TRUE;
+}
+
 static void
 cc_keyboard_panel_set_property (GObject      *object,
                                guint         property_id,
@@ -629,6 +699,7 @@ cc_keyboard_panel_finalize (GObject *object)
 
   g_clear_pointer (&self->pictures_regex, g_regex_unref);
   g_clear_object (&self->accelerator_sizegroup);
+  g_clear_object (&self->input_source_settings);
 
   cc_keyboard_option_clear_all ();
 
@@ -689,9 +760,11 @@ cc_keyboard_panel_class_init (CcKeyboardPanelClass *klass)
   gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, search_button);
   gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, search_entry);
   gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, shortcuts_listbox);
+  gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, value_alternate_chars);
 
   gtk_widget_class_bind_template_callback (widget_class, reset_all_clicked_cb);
   gtk_widget_class_bind_template_callback (widget_class, shortcut_row_activated);
+  gtk_widget_class_bind_template_callback (widget_class, alternate_chars_activated);
 }
 
 static void
@@ -713,6 +786,20 @@ cc_keyboard_panel_init (CcKeyboardPanel *self)
 
   g_object_unref (provider);
 
+  /* Alternate characters key */
+  self->input_source_settings = g_settings_new ("org.gnome.desktop.input-sources");
+  g_settings_bind_with_mapping (self->input_source_settings,
+                                "xkb-options",
+                                self->value_alternate_chars,
+                                "label",
+                                G_SETTINGS_BIND_GET,
+                                transform_binding_to_alt_chars,
+                                NULL,
+                                self->value_alternate_chars,
+                                NULL);
+
+  self->alt_chars_key_dialog = cc_alt_chars_key_dialog_new (self->input_source_settings);
+
   /* Shortcut manager */
   self->manager = cc_keyboard_manager_new ();
 
diff --git a/panels/keyboard/cc-keyboard-panel.ui b/panels/keyboard/cc-keyboard-panel.ui
index aad179e5c..af087b7ab 100644
--- a/panels/keyboard/cc-keyboard-panel.ui
+++ b/panels/keyboard/cc-keyboard-panel.ui
@@ -53,6 +53,37 @@
                 <property name="margin_right">18</property>
                 <property name="spacing">12</property>
                 <property name="halign">center</property>
+                <child>
+                  <object class="GtkFrame">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkListBox" id="alternate_chars_listbox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="selection-mode">none</property>
+                        <property name="width-request">250</property>
+                        <signal name="row-activated" handler="alternate_chars_activated" 
object="CcKeyboardPanel" swapped="no" />
+                        <child>
+                          <object class="HdyActionRow">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="use-underline">true</property>
+                            <property name="title" translatable="yes">Alternate Characters Key</property>
+                            <property name="subtitle" translatable="yes">Hold down and type to enter 
different characters</property>
+                            <child type="action">
+                              <object class="GtkLabel" id="value_alternate_chars">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="label" translatable="no">Right Alt</property>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
                 <child>
                   <object class="GtkFrame">
                     <property name="visible">True</property>
diff --git a/panels/keyboard/keyboard.gresource.xml b/panels/keyboard/keyboard.gresource.xml
index 81566ef6d..0283dae2a 100644
--- a/panels/keyboard/keyboard.gresource.xml
+++ b/panels/keyboard/keyboard.gresource.xml
@@ -2,6 +2,7 @@
 <gresources>
   <gresource prefix="/org/gnome/control-center/keyboard">
     <file preprocess="xml-stripblanks">enter-keyboard-shortcut.svg</file>
+    <file preprocess="xml-stripblanks">cc-alt-chars-key-dialog.ui</file>
     <file preprocess="xml-stripblanks">cc-keyboard-panel.ui</file>
     <file preprocess="xml-stripblanks">cc-keyboard-shortcut-editor.ui</file>
   </gresource>
diff --git a/panels/keyboard/meson.build b/panels/keyboard/meson.build
index f90a52c84..2f61ed071 100644
--- a/panels/keyboard/meson.build
+++ b/panels/keyboard/meson.build
@@ -56,6 +56,7 @@ foreach file: xml_files
 endforeach
 
 sources = files(
+  'cc-alt-chars-key-dialog.c',
   'cc-keyboard-panel.c',
   'cc-keyboard-item.c',
   'cc-keyboard-manager.c',


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]