diff options
author | Bastien Nocera <hadess@hadess.net> | 2018-03-29 13:33:15 +0200 |
---|---|---|
committer | Georges Basile Stavracas Neto <georges.stavracas@gmail.com> | 2018-06-21 17:49:37 +0000 |
commit | ffe057adc8b0d84b8a53ad1c4701dce157efb3f4 (patch) | |
tree | aa54cd1837820479985d40b6373b716e8849fa32 | |
parent | 7512860abc0830a21fa1d9abbb16710a0f305e18 (diff) | |
download | gnome-control-center-wip/alt-chars-key.tar.gz |
keyboard: Add "Alternate Characters Key" configurationwip/alt-chars-key
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:
https://raw.githubusercontent.com/gnome-design-team/gnome-mockups/master/system-settings/keyboard/keyboard-wires.png
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.
-rw-r--r-- | panels/keyboard/alt-chars-key.ui | 177 | ||||
-rw-r--r-- | panels/keyboard/cc-keyboard-panel.c | 139 | ||||
-rw-r--r-- | panels/keyboard/gnome-keyboard-panel.ui | 96 | ||||
-rw-r--r-- | panels/keyboard/keyboard.gresource.xml | 1 |
4 files changed, 412 insertions, 1 deletions
diff --git a/panels/keyboard/alt-chars-key.ui b/panels/keyboard/alt-chars-key.ui new file mode 100644 index 000000000..c6f7eeb30 --- /dev/null +++ b/panels/keyboard/alt-chars-key.ui @@ -0,0 +1,177 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.22.0 --> +<interface> + <requires lib="gtk+" version="3.20"/> + <object class="GtkDialog" id="alt_chars_key_dialog"> + <property name="can_focus">False</property> + <property name="resizable">False</property> + <property name="type_hint">dialog</property> + <child internal-child="vbox"> + <object class="GtkBox"> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">2</property> + <child internal-child="action_area"> + <object class="GtkButtonBox"> + <property name="can_focus">False</property> + <property name="layout_style">end</property> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">12</property> + <property name="margin_right">12</property> + <property name="margin_top">12</property> + <property name="margin_bottom">12</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">12</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">50</property> + <property name="max_width_chars">50</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </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="radiobutton_leftalt"> + <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> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="radiobutton_rightalt"> + <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">radiobutton_leftalt</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="radiobutton_leftsuper"> + <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">radiobutton_leftalt</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="radiobutton_rightsuper"> + <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">radiobutton_leftalt</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="radiobutton_menukey"> + <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">radiobutton_leftalt</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="radiobutton_rightctrl"> + <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">radiobutton_leftalt</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + <child type="titlebar"> + <placeholder/> + </child> + <child internal-child="headerbar"> + <object class="GtkHeaderBar"> + <property name="can_focus">False</property> + <property name="show_close_button">True</property> + <child> + <placeholder/> + </child> + </object> + </child> + </object> +</interface> diff --git a/panels/keyboard/cc-keyboard-panel.c b/panels/keyboard/cc-keyboard-panel.c index f5dd6e822..0f9a72021 100644 --- a/panels/keyboard/cc-keyboard-panel.c +++ b/panels/keyboard/cc-keyboard-panel.c @@ -57,6 +57,10 @@ struct _CcKeyboardPanel GtkListBoxRow *add_shortcut_row; GtkSizeGroup *accelerator_sizegroup; + /* Alternate characters key */ + GSettings *input_source_settings; + GtkWidget *value_alternate_chars; + /* Custom shortcut dialog */ GtkWidget *shortcut_editor; @@ -77,6 +81,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, @@ -261,7 +280,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); @@ -595,6 +614,113 @@ shortcut_row_activated (GtkWidget *button, } static void +active_lv3_changed (GtkToggleButton *button, + CcKeyboardPanel *self) +{ + char **options; + GPtrArray *array; + guint i; + gboolean found; + + if (!gtk_toggle_button_get_active (button)) + return; + + /* Either replace the existing "lv3:" option in the string + * array, or add the option at the end */ + array = g_ptr_array_new_with_free_func (g_free); + 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:")) { + found = TRUE; + g_ptr_array_add (array, g_strdup ((char *) g_object_get_data (G_OBJECT (button), "option"))); + } else { + g_ptr_array_add (array, g_strdup (options[i])); + } + } + g_strfreev (options); + + if (!found) + g_ptr_array_add (array, g_strdup ((char *) g_object_get_data (G_OBJECT (button), "option"))); + + g_ptr_array_add (array, NULL); + + g_settings_set_strv (self->input_source_settings, "xkb-options", + (const char **) array->pdata); + g_ptr_array_free (array, TRUE); +} + +static void +alternate_chars_activated (GtkWidget *button, + GtkListBoxRow *row, + CcKeyboardPanel *self) +{ + GtkBuilder *builder; + GtkWidget *dialog; + guint i; + const char *current_lv3_widget; + + current_lv3_widget = g_object_get_data (G_OBJECT (self->value_alternate_chars), "lv3_widget_name"); + builder = gtk_builder_new_from_resource ("/org/gnome/control-center/keyboard/alt-chars-key.ui"); + for (i = 0; i < G_N_ELEMENTS(lv3_xkb_options); i++) { + GObject *label; + + label = gtk_builder_get_object (builder, lv3_xkb_options[i].widget_name); + g_object_set_data (label, "option", (gpointer) lv3_xkb_options[i].xkb_option); + if (g_str_equal (current_lv3_widget, lv3_xkb_options[i].widget_name)) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (label), TRUE); + + g_signal_connect (label, "toggled", G_CALLBACK (active_lv3_changed), self); + } + dialog = GTK_WIDGET (gtk_builder_get_object (builder, "alt_chars_key_dialog")); + gtk_window_set_title (GTK_WINDOW (dialog), _("Alternate Characters Key")); + gtk_window_set_transient_for (GTK_WINDOW (dialog), + GTK_WINDOW (cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (self))))); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + g_object_unref (builder); +} + +static gboolean +transform_binding_to_alt_chars (GValue *value, + GVariant *variant, + gpointer user_data) +{ + GObject *value_alternate_chars = 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)) { + g_value_set_string (value, + g_dpgettext2 (NULL, "keyboard key", lv3_xkb_options[j].label)); + g_object_set_data (value_alternate_chars, + "lv3_widget_name", + (gpointer) lv3_xkb_options[j].widget_name); + return TRUE; + } + } + } + +bail: + g_value_set_string (value, + g_dpgettext2 (NULL, "keyboard key", lv3_xkb_options[DEFAULT_LV3_OPTION].label)); + g_object_set_data (value_alternate_chars, + "lv3_widget_name", + (gpointer) lv3_xkb_options[DEFAULT_LV3_OPTION].widget_name); + return TRUE; +} + +static void cc_keyboard_panel_set_property (GObject *object, guint property_id, const GValue *value, @@ -624,6 +750,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 (); @@ -680,9 +807,11 @@ cc_keyboard_panel_class_init (CcKeyboardPanelClass *klass) gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, search_bar); 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, 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 @@ -704,6 +833,14 @@ 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); + /* Shortcut manager */ self->manager = cc_keyboard_manager_new (); diff --git a/panels/keyboard/gnome-keyboard-panel.ui b/panels/keyboard/gnome-keyboard-panel.ui index d5924f5d4..f17706edb 100644 --- a/panels/keyboard/gnome-keyboard-panel.ui +++ b/panels/keyboard/gnome-keyboard-panel.ui @@ -53,6 +53,102 @@ <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="GtkListBoxRow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="expand">True</property> + <property name="border_width">6</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel" id="heading_alternate_chars"> + <property name="hexpand">True</property> + <property name="expand">True</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_start">12</property> + <property name="margin_end">12</property> + <property name="margin_top">6</property> + <property name="margin_bottom">0</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">_Alternate Characters Key</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">value_alternate_chars</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="subtitle_alternate_chars"> + <property name="hexpand">True</property> + <property name="expand">True</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_start">12</property> + <property name="margin_end">12</property> + <property name="margin_top">0</property> + <property name="margin_bottom">6</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Hold down and type to enter different characters</property> + <property name="use_underline">False</property> + <style> + <class name="dim-label"/> + </style> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + <child> + <object class="GtkLabel" id="value_alternate_chars"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="margin_start">12</property> + <property name="margin_end">12</property> + <property name="margin_top">12</property> + <property name="margin_bottom">12</property> + <property name="label" translatable="no">Right Alt</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> + </child> + </object> + </child> + </object> + </child> <child> <object class="GtkBox"> <property name="visible">True</property> diff --git a/panels/keyboard/keyboard.gresource.xml b/panels/keyboard/keyboard.gresource.xml index effbe913a..d443c8240 100644 --- a/panels/keyboard/keyboard.gresource.xml +++ b/panels/keyboard/keyboard.gresource.xml @@ -4,5 +4,6 @@ <file preprocess="xml-stripblanks">enter-keyboard-shortcut.svg</file> <file preprocess="xml-stripblanks">gnome-keyboard-panel.ui</file> <file preprocess="xml-stripblanks">shortcut-editor.ui</file> + <file preprocess="xml-stripblanks">alt-chars-key.ui</file> </gresource> </gresources> |