summaryrefslogtreecommitdiffstats
path: root/panels/keyboard/cc-keyboard-panel.c
diff options
context:
space:
mode:
Diffstat (limited to 'panels/keyboard/cc-keyboard-panel.c')
-rw-r--r--panels/keyboard/cc-keyboard-panel.c266
1 files changed, 266 insertions, 0 deletions
diff --git a/panels/keyboard/cc-keyboard-panel.c b/panels/keyboard/cc-keyboard-panel.c
new file mode 100644
index 0000000..2e91fe7
--- /dev/null
+++ b/panels/keyboard/cc-keyboard-panel.c
@@ -0,0 +1,266 @@
+/* cc-keyboard-panel.c
+ *
+ * Copyright (C) 2010 Intel, Inc
+ * Copyright (C) 2016 Endless, Inc
+ * Copyright (C) 2020 System76, Inc.
+ *
+ * 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/>.
+ *
+ * Author: Thomas Wood <thomas.wood@intel.com>
+ * Georges Basile Stavracas Neto <gbsneto@gnome.org>
+ * Ian Douglas Scott <idscott@system76.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <glib/gi18n.h>
+
+#include "cc-keyboard-panel.h"
+#include "cc-keyboard-resources.h"
+#include "cc-keyboard-shortcut-dialog.h"
+#include "cc-input-list-box.h"
+#include "cc-xkb-modifier-dialog.h"
+
+#include "keyboard-shortcuts.h"
+
+struct _CcKeyboardPanel
+{
+ CcPanel parent_instance;
+
+ GtkCheckButton *per_window_source;
+ GtkCheckButton *same_source;
+ GSettings *keybindings_settings;
+
+ GSettings *input_source_settings;
+ AdwPreferencesGroup *input_switch_group;
+ AdwActionRow *alt_chars_row;
+ AdwActionRow *compose_row;
+ GtkWidget *value_alternate_chars;
+ GtkWidget *value_compose;
+
+ AdwActionRow *common_shortcuts_row;
+};
+
+CC_PANEL_REGISTER (CcKeyboardPanel, cc_keyboard_panel)
+
+enum {
+ PROP_0,
+ PROP_PARAMETERS
+};
+
+static const CcXkbModifier LV3_MODIFIER = {
+ "lv3:",
+ 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", "Left Alt"), "lv3:lalt_switch" },
+ { NC_("keyboard key", "Right Alt"), "lv3:ralt_switch" },
+ { NC_("keyboard key", "Left Super"), "lv3:lwin_switch" },
+ { NC_("keyboard key", "Right Super"), "lv3:rwin_switch" },
+ { NC_("keyboard key", "Menu key"), "lv3:menu_switch" },
+ { NC_("keyboard key", "Right Ctrl"), "lv3:switch" },
+ { NULL, NULL }
+ },
+ "lv3:ralt_switch",
+};
+
+static const CcXkbModifier COMPOSE_MODIFIER = {
+ "compose:",
+ N_("Compose Key"),
+ N_("The compose key allows a wide variety of characters to be entered. To use it, press compose then a sequence of characters. "
+ " For example, compose key followed by <b>C</b> and <b>o</b> will enter <b>©</b>, "
+ "<b>a</b> followed by <b>'</b> will enter <b>á</b>."),
+ (CcXkbOption[]){
+ { NC_("keyboard key", "Left Alt"), "compose:lalt" },
+ { NC_("keyboard key", "Right Alt"), "compose:ralt" },
+ { NC_("keyboard key", "Left Super"), "compose:lwin" },
+ { NC_("keyboard key", "Right Super"), "compose:rwin" },
+ { NC_("keyboard key", "Menu key"), "compose:menu" },
+ { NC_("keyboard key", "Right Ctrl"), "compose:rctrl" },
+ { NC_("keyboard key", "Caps Lock"), "compose:caps" },
+ { NC_("keyboard key", "Scroll Lock"), "compose:sclk" },
+ { NC_("keyboard key", "Print Screen"), "compose:prsc" },
+ { NULL, NULL }
+ },
+ NULL,
+};
+
+static void
+special_chars_activated (AdwActionRow *row,
+ CcKeyboardPanel *self)
+{
+ const CcXkbModifier *modifier;
+ GtkWindow *window, *dialog;
+
+ window = GTK_WINDOW (cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (self))));
+
+ if (row == self->alt_chars_row)
+ modifier = &LV3_MODIFIER;
+ else if (row == self->compose_row)
+ modifier = &COMPOSE_MODIFIER;
+ else
+ return;
+
+ dialog = GTK_WINDOW (cc_xkb_modifier_dialog_new (self->input_source_settings, modifier));
+
+ gtk_window_set_transient_for (dialog, window);
+ gtk_widget_show (GTK_WIDGET (dialog));
+}
+
+static void
+keyboard_shortcuts_activated (AdwActionRow *row,
+ CcKeyboardPanel *self)
+{
+ GtkWindow *window;
+ GtkWidget *shortcut_dialog;
+
+ if (row == self->common_shortcuts_row)
+ {
+ window = GTK_WINDOW (cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (self))));
+
+ shortcut_dialog = cc_keyboard_shortcut_dialog_new ();
+ gtk_window_set_transient_for (GTK_WINDOW (shortcut_dialog), window);
+ gtk_widget_show (GTK_WIDGET (shortcut_dialog));
+ }
+}
+
+static void
+cc_keyboard_panel_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id)
+ {
+ case PROP_PARAMETERS:
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static const char *
+cc_keyboard_panel_get_help_uri (CcPanel *panel)
+{
+ return "help:gnome-help/keyboard";
+}
+
+static void
+cc_keyboard_panel_finalize (GObject *object)
+{
+ CcKeyboardPanel *self = CC_KEYBOARD_PANEL (object);
+
+ g_clear_object (&self->input_source_settings);
+ g_clear_object (&self->keybindings_settings);
+
+ G_OBJECT_CLASS (cc_keyboard_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_keyboard_panel_class_init (CcKeyboardPanelClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
+
+ panel_class->get_help_uri = cc_keyboard_panel_get_help_uri;
+
+ object_class->set_property = cc_keyboard_panel_set_property;
+ object_class->finalize = cc_keyboard_panel_finalize;
+
+ g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
+
+ g_type_ensure (CC_TYPE_INPUT_LIST_BOX);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/keyboard/cc-keyboard-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, input_switch_group);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, per_window_source);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, same_source);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, alt_chars_row);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, compose_row);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, value_alternate_chars);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, value_compose);
+ gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, common_shortcuts_row);
+
+ gtk_widget_class_bind_template_callback (widget_class, special_chars_activated);
+ gtk_widget_class_bind_template_callback (widget_class, keyboard_shortcuts_activated);
+}
+
+static gboolean
+translate_switch_input_source (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ g_autofree const gchar **strv = NULL;
+ g_autofree gchar *accel_text = NULL;
+ g_autofree gchar *label = NULL;
+ CcKeyCombo combo = { 0 };
+
+ strv = g_variant_get_strv (variant, NULL);
+
+ gtk_accelerator_parse (strv[0] ? strv[0] : "", &combo.keyval, &combo.mask);
+ accel_text = convert_keysym_state_to_string (&combo);
+
+ label = g_strdup_printf (_("Input sources can be switched using the %s "
+ "keyboard shortcut.\nThis can be changed in "
+ "the keyboard shortcut settings."),
+ accel_text);
+
+ g_value_set_string (value, label);
+
+ return TRUE;
+}
+
+static void
+cc_keyboard_panel_init (CcKeyboardPanel *self)
+{
+ g_resources_register (cc_keyboard_get_resource ());
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->input_source_settings = g_settings_new ("org.gnome.desktop.input-sources");
+
+ /* "Input Source Switching" section */
+ g_settings_bind (self->input_source_settings, "per-window",
+ self->same_source, "active",
+ G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_INVERT_BOOLEAN);
+ self->keybindings_settings = g_settings_new ("org.gnome.desktop.wm.keybindings");
+ g_settings_bind_with_mapping (self->keybindings_settings, "switch-input-source",
+ self->input_switch_group, "description",
+ G_SETTINGS_BIND_GET,
+ translate_switch_input_source,
+ NULL, NULL, NULL);
+
+ /* "Type Special Characters" section */
+ g_settings_bind_with_mapping (self->input_source_settings,
+ "xkb-options",
+ self->value_alternate_chars,
+ "label",
+ G_SETTINGS_BIND_GET,
+ xcb_modifier_transform_binding_to_label,
+ NULL,
+ (gpointer)&LV3_MODIFIER,
+ NULL);
+ g_settings_bind_with_mapping (self->input_source_settings,
+ "xkb-options",
+ self->value_compose,
+ "label",
+ G_SETTINGS_BIND_GET,
+ xcb_modifier_transform_binding_to_label,
+ NULL,
+ (gpointer)&COMPOSE_MODIFIER,
+ NULL);
+}