Line |
Branch |
Exec |
Source |
1 |
|
|
/* cc-keyboard-panel.c |
2 |
|
|
* |
3 |
|
|
* Copyright (C) 2010 Intel, Inc |
4 |
|
|
* Copyright (C) 2016 Endless, Inc |
5 |
|
|
* Copyright (C) 2020 System76, Inc. |
6 |
|
|
* |
7 |
|
|
* This program is free software; you can redistribute it and/or modify |
8 |
|
|
* it under the terms of the GNU General Public License as published by |
9 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
10 |
|
|
* (at your option) any later version. |
11 |
|
|
* |
12 |
|
|
* This program is distributed in the hope that it will be useful, |
13 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
|
|
* GNU General Public License for more details. |
16 |
|
|
* |
17 |
|
|
* You should have received a copy of the GNU General Public License |
18 |
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>. |
19 |
|
|
* |
20 |
|
|
* Author: Thomas Wood <thomas.wood@intel.com> |
21 |
|
|
* Georges Basile Stavracas Neto <gbsneto@gnome.org> |
22 |
|
|
* Ian Douglas Scott <idscott@system76.com> |
23 |
|
|
* |
24 |
|
|
* SPDX-License-Identifier: GPL-2.0-or-later |
25 |
|
|
*/ |
26 |
|
|
|
27 |
|
|
#include <glib/gi18n.h> |
28 |
|
|
|
29 |
|
|
#include "cc-keyboard-panel.h" |
30 |
|
|
#include "cc-keyboard-resources.h" |
31 |
|
|
#include "cc-keyboard-shortcut-dialog.h" |
32 |
|
|
#include "cc-input-list-box.h" |
33 |
|
|
#include "cc-xkb-modifier-dialog.h" |
34 |
|
|
#include "cc-list-row.h" |
35 |
|
|
|
36 |
|
|
#include "keyboard-shortcuts.h" |
37 |
|
|
|
38 |
|
|
struct _CcKeyboardPanel |
39 |
|
|
{ |
40 |
|
|
CcPanel parent_instance; |
41 |
|
|
|
42 |
|
|
GtkCheckButton *per_window_source; |
43 |
|
|
GtkCheckButton *same_source; |
44 |
|
|
GSettings *keybindings_settings; |
45 |
|
|
|
46 |
|
|
GSettings *input_source_settings; |
47 |
|
|
AdwPreferencesGroup *input_switch_group; |
48 |
|
|
CcListRow *alt_chars_row; |
49 |
|
|
CcListRow *compose_row; |
50 |
|
|
|
51 |
|
|
AdwActionRow *common_shortcuts_row; |
52 |
|
|
}; |
53 |
|
|
|
54 |
|
✗ |
CC_PANEL_REGISTER (CcKeyboardPanel, cc_keyboard_panel) |
55 |
|
|
|
56 |
|
|
enum { |
57 |
|
|
PROP_0, |
58 |
|
|
PROP_PARAMETERS |
59 |
|
|
}; |
60 |
|
|
|
61 |
|
|
static const CcXkbModifier LV3_MODIFIER = { |
62 |
|
|
"lv3:", |
63 |
|
|
N_("Alternate Characters Key"), |
64 |
|
|
N_("The alternate characters key can be used to enter additional characters. These are sometimes printed as a third-option on your keyboard."), |
65 |
|
|
(CcXkbOption[]){ |
66 |
|
|
{ NC_("keyboard key", "Left Alt"), "lv3:lalt_switch" }, |
67 |
|
|
{ NC_("keyboard key", "Right Alt"), "lv3:ralt_switch" }, |
68 |
|
|
{ NC_("keyboard key", "Left Super"), "lv3:lwin_switch" }, |
69 |
|
|
{ NC_("keyboard key", "Right Super"), "lv3:rwin_switch" }, |
70 |
|
|
{ NC_("keyboard key", "Menu key"), "lv3:menu_switch" }, |
71 |
|
|
{ NC_("keyboard key", "Right Ctrl"), "lv3:switch" }, |
72 |
|
|
{ NULL, NULL } |
73 |
|
|
}, |
74 |
|
|
"lv3:ralt_switch", |
75 |
|
|
}; |
76 |
|
|
|
77 |
|
|
static const CcXkbModifier COMPOSE_MODIFIER = { |
78 |
|
|
"compose:", |
79 |
|
|
N_("Compose Key"), |
80 |
|
|
N_("The compose key allows a wide variety of characters to be entered. To use it, press compose then a sequence of characters. " |
81 |
|
|
" For example, compose key followed by <b>C</b> and <b>o</b> will enter <b>©</b>, " |
82 |
|
|
"<b>a</b> followed by <b>'</b> will enter <b>á</b>."), |
83 |
|
|
(CcXkbOption[]){ |
84 |
|
|
{ NC_("keyboard key", "Right Alt"), "compose:ralt" }, |
85 |
|
|
{ NC_("keyboard key", "Left Super"), "compose:lwin" }, |
86 |
|
|
{ NC_("keyboard key", "Right Super"), "compose:rwin" }, |
87 |
|
|
{ NC_("keyboard key", "Menu key"), "compose:menu" }, |
88 |
|
|
{ NC_("keyboard key", "Left Ctrl"), "compose:lctrl" }, |
89 |
|
|
{ NC_("keyboard key", "Right Ctrl"), "compose:rctrl" }, |
90 |
|
|
{ NC_("keyboard key", "Caps Lock"), "compose:caps" }, |
91 |
|
|
{ NC_("keyboard key", "Scroll Lock"), "compose:sclk" }, |
92 |
|
|
{ NC_("keyboard key", "Print Screen"), "compose:prsc" }, |
93 |
|
|
{ NC_("keyboard key", "Insert"), "compose:ins" }, |
94 |
|
|
{ NULL, NULL } |
95 |
|
|
}, |
96 |
|
|
NULL, |
97 |
|
|
}; |
98 |
|
|
|
99 |
|
|
static void |
100 |
|
✗ |
show_modifier_dialog (CcKeyboardPanel *self, const CcXkbModifier *modifier) |
101 |
|
|
{ |
102 |
|
|
AdwDialog *dialog; |
103 |
|
|
|
104 |
|
✗ |
dialog = ADW_DIALOG (cc_xkb_modifier_dialog_new (self->input_source_settings, modifier)); |
105 |
|
|
|
106 |
|
✗ |
adw_dialog_present (dialog, GTK_WIDGET (self)); |
107 |
|
✗ |
} |
108 |
|
|
|
109 |
|
|
static void |
110 |
|
✗ |
alt_chars_row_activated (CcKeyboardPanel *self) |
111 |
|
|
{ |
112 |
|
✗ |
show_modifier_dialog (self, &LV3_MODIFIER); |
113 |
|
✗ |
} |
114 |
|
|
|
115 |
|
|
static void |
116 |
|
✗ |
compose_row_activated (CcKeyboardPanel *self) |
117 |
|
|
{ |
118 |
|
✗ |
show_modifier_dialog (self, &COMPOSE_MODIFIER); |
119 |
|
✗ |
} |
120 |
|
|
|
121 |
|
|
static void |
122 |
|
✗ |
keyboard_shortcuts_activated (CcKeyboardPanel *self) |
123 |
|
|
{ |
124 |
|
|
GtkWindow *window; |
125 |
|
|
GtkWidget *shortcut_dialog; |
126 |
|
|
|
127 |
|
✗ |
window = GTK_WINDOW (cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (self)))); |
128 |
|
|
|
129 |
|
✗ |
shortcut_dialog = cc_keyboard_shortcut_dialog_new (); |
130 |
|
✗ |
gtk_window_set_transient_for (GTK_WINDOW (shortcut_dialog), window); |
131 |
|
✗ |
gtk_window_present (GTK_WINDOW (shortcut_dialog)); |
132 |
|
✗ |
} |
133 |
|
|
|
134 |
|
|
static void |
135 |
|
✗ |
cc_keyboard_panel_set_property (GObject *object, |
136 |
|
|
guint property_id, |
137 |
|
|
const GValue *value, |
138 |
|
|
GParamSpec *pspec) |
139 |
|
|
{ |
140 |
|
✗ |
switch (property_id) |
141 |
|
|
{ |
142 |
|
✗ |
case PROP_PARAMETERS: |
143 |
|
✗ |
break; |
144 |
|
|
|
145 |
|
✗ |
default: |
146 |
|
✗ |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); |
147 |
|
|
} |
148 |
|
✗ |
} |
149 |
|
|
|
150 |
|
|
static const char * |
151 |
|
✗ |
cc_keyboard_panel_get_help_uri (CcPanel *panel) |
152 |
|
|
{ |
153 |
|
✗ |
return "help:gnome-help/keyboard"; |
154 |
|
|
} |
155 |
|
|
|
156 |
|
|
static void |
157 |
|
✗ |
cc_keyboard_panel_finalize (GObject *object) |
158 |
|
|
{ |
159 |
|
✗ |
CcKeyboardPanel *self = CC_KEYBOARD_PANEL (object); |
160 |
|
|
|
161 |
|
✗ |
g_clear_object (&self->input_source_settings); |
162 |
|
✗ |
g_clear_object (&self->keybindings_settings); |
163 |
|
|
|
164 |
|
✗ |
G_OBJECT_CLASS (cc_keyboard_panel_parent_class)->finalize (object); |
165 |
|
✗ |
} |
166 |
|
|
|
167 |
|
|
static void |
168 |
|
✗ |
cc_keyboard_panel_class_init (CcKeyboardPanelClass *klass) |
169 |
|
|
{ |
170 |
|
✗ |
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); |
171 |
|
✗ |
GObjectClass *object_class = G_OBJECT_CLASS (klass); |
172 |
|
✗ |
CcPanelClass *panel_class = CC_PANEL_CLASS (klass); |
173 |
|
|
|
174 |
|
✗ |
panel_class->get_help_uri = cc_keyboard_panel_get_help_uri; |
175 |
|
|
|
176 |
|
✗ |
object_class->set_property = cc_keyboard_panel_set_property; |
177 |
|
✗ |
object_class->finalize = cc_keyboard_panel_finalize; |
178 |
|
|
|
179 |
|
✗ |
g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters"); |
180 |
|
|
|
181 |
|
✗ |
g_type_ensure (CC_TYPE_INPUT_LIST_BOX); |
182 |
|
✗ |
g_type_ensure (CC_TYPE_LIST_ROW); |
183 |
|
|
|
184 |
|
✗ |
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/keyboard/cc-keyboard-panel.ui"); |
185 |
|
|
|
186 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, input_switch_group); |
187 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, per_window_source); |
188 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, same_source); |
189 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, alt_chars_row); |
190 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, compose_row); |
191 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, common_shortcuts_row); |
192 |
|
|
|
193 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, alt_chars_row_activated); |
194 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, compose_row_activated); |
195 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, keyboard_shortcuts_activated); |
196 |
|
✗ |
} |
197 |
|
|
|
198 |
|
|
static gboolean |
199 |
|
✗ |
translate_switch_input_source (GValue *value, |
200 |
|
|
GVariant *variant, |
201 |
|
|
gpointer user_data) |
202 |
|
|
{ |
203 |
|
✗ |
g_autofree const gchar **strv = NULL; |
204 |
|
✗ |
g_autofree gchar *accel_text = NULL; |
205 |
|
✗ |
g_autofree gchar *label = NULL; |
206 |
|
✗ |
CcKeyCombo combo = { 0 }; |
207 |
|
|
|
208 |
|
✗ |
strv = g_variant_get_strv (variant, NULL); |
209 |
|
|
|
210 |
|
✗ |
gtk_accelerator_parse (strv[0] ? strv[0] : "", &combo.keyval, &combo.mask); |
211 |
|
✗ |
accel_text = convert_keysym_state_to_string (&combo); |
212 |
|
|
|
213 |
|
✗ |
label = g_strdup_printf (_("Input sources can be switched using the %s " |
214 |
|
|
"keyboard shortcut.\nThis can be changed in " |
215 |
|
|
"the keyboard shortcut settings."), |
216 |
|
|
accel_text); |
217 |
|
|
|
218 |
|
✗ |
g_value_set_string (value, label); |
219 |
|
|
|
220 |
|
✗ |
return TRUE; |
221 |
|
|
} |
222 |
|
|
|
223 |
|
|
static void |
224 |
|
✗ |
cc_keyboard_panel_init (CcKeyboardPanel *self) |
225 |
|
|
{ |
226 |
|
✗ |
g_resources_register (cc_keyboard_get_resource ()); |
227 |
|
|
|
228 |
|
✗ |
gtk_widget_init_template (GTK_WIDGET (self)); |
229 |
|
|
|
230 |
|
✗ |
self->input_source_settings = g_settings_new ("org.gnome.desktop.input-sources"); |
231 |
|
|
|
232 |
|
|
/* "Input Source Switching" section */ |
233 |
|
✗ |
g_settings_bind (self->input_source_settings, "per-window", |
234 |
|
✗ |
self->same_source, "active", |
235 |
|
|
G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_INVERT_BOOLEAN); |
236 |
|
✗ |
self->keybindings_settings = g_settings_new ("org.gnome.desktop.wm.keybindings"); |
237 |
|
✗ |
g_settings_bind_with_mapping (self->keybindings_settings, "switch-input-source", |
238 |
|
✗ |
self->input_switch_group, "description", |
239 |
|
|
G_SETTINGS_BIND_GET, |
240 |
|
|
translate_switch_input_source, |
241 |
|
|
NULL, NULL, NULL); |
242 |
|
|
|
243 |
|
|
/* "Type Special Characters" section */ |
244 |
|
✗ |
g_settings_bind_with_mapping (self->input_source_settings, |
245 |
|
|
"xkb-options", |
246 |
|
✗ |
self->alt_chars_row, |
247 |
|
|
"secondary-label", |
248 |
|
|
G_SETTINGS_BIND_GET, |
249 |
|
|
xcb_modifier_transform_binding_to_label, |
250 |
|
|
NULL, |
251 |
|
|
(gpointer)&LV3_MODIFIER, |
252 |
|
|
NULL); |
253 |
|
✗ |
g_settings_bind_with_mapping (self->input_source_settings, |
254 |
|
|
"xkb-options", |
255 |
|
✗ |
self->compose_row, |
256 |
|
|
"secondary-label", |
257 |
|
|
G_SETTINGS_BIND_GET, |
258 |
|
|
xcb_modifier_transform_binding_to_label, |
259 |
|
|
NULL, |
260 |
|
|
(gpointer)&COMPOSE_MODIFIER, |
261 |
|
|
NULL); |
262 |
|
✗ |
} |
263 |
|
|
|