gnome-control-center/panels/keyboard/cc-keyboard-panel.c
Georges Basile Stavracas Neto d7e794e7ab keyboard: Port to GTK4
Drop the wm-common insanity.
2021-12-14 22:34:21 -03:00

294 lines
10 KiB
C

/* 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;
GtkListBox *input_source_list;
GtkCheckButton *per_window_source;
GtkCheckButton *same_source;
GSettings *keybindings_settings;
GSettings *input_source_settings;
GtkLabel *input_switch_description;
GtkListBox *special_chars_list;
GtkListBoxRow *alt_chars_row;
GtkListBoxRow *compose_row;
GtkWidget *value_alternate_chars;
GtkWidget *value_compose;
GtkListBoxRow *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 const gchar *custom_css =
".keyboard-panel-radio-button {"
" padding-left: 6px;"
" padding-right: 12px;"
" padding-top: 12px;"
" padding-bottom: 12px;"
"}";
static void
special_chars_activated (GtkWidget *button,
GtkListBoxRow *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 (GtkWidget *button,
GtkListBoxRow *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_source_list);
gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, input_switch_description);
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, special_chars_list);
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)
{
GtkCssProvider *provider;
g_resources_register (cc_keyboard_get_resource ());
gtk_widget_init_template (GTK_WIDGET (self));
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (provider, custom_css, -1);
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 1);
g_object_unref (provider);
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->per_window_source, "active",
G_SETTINGS_BIND_DEFAULT);
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_description, "label",
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);
}