1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 
3 /*
4  * Copyright 2014 Red Hat, Inc.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  *
19  * Author: Carlos Garnacho <carlosg@gnome.org>
20  */
21 
22 /**
23  * SECTION:input-settings
24  * @title: MetaInputSettings
25  * @short_description: Mutter input device configuration
26  */
27 
28 #include "config.h"
29 
30 #include <glib/gi18n-lib.h>
31 #include <string.h>
32 
33 #include "backends/meta-backend-private.h"
34 #include "backends/meta-input-device-private.h"
35 #include "backends/meta-input-settings-private.h"
36 #include "backends/meta-input-mapper-private.h"
37 #include "backends/meta-logical-monitor.h"
38 #include "backends/meta-monitor.h"
39 #include "core/display-private.h"
40 #include "meta/util.h"
41 
42 static GQuark quark_tool_settings = 0;
43 
44 typedef struct _MetaInputSettingsPrivate MetaInputSettingsPrivate;
45 typedef struct _DeviceMappingInfo DeviceMappingInfo;
46 typedef struct _CurrentToolInfo CurrentToolInfo;
47 
48 struct _CurrentToolInfo
49 {
50   MetaInputSettings *input_settings;
51   ClutterInputDevice *device;
52   ClutterInputDeviceTool *tool;
53   GSettings *settings;
54   gulong changed_id;
55 };
56 
57 struct _DeviceMappingInfo
58 {
59   MetaInputSettings *input_settings;
60   ClutterInputDevice *device;
61   GSettings *settings;
62   gulong changed_id;
63   guint *group_modes;
64   double aspect_ratio;
65 };
66 
67 struct _MetaInputSettingsPrivate
68 {
69   ClutterSeat *seat;
70   gulong monitors_changed_id;
71 
72   GSettings *mouse_settings;
73   GSettings *touchpad_settings;
74   GSettings *trackball_settings;
75   GSettings *keyboard_settings;
76   GSettings *keyboard_a11y_settings;
77 
78   GList *devices;
79   GHashTable *mappable_devices;
80 
81   GHashTable *current_tools;
82 
83   GHashTable *two_finger_devices;
84 
85   MetaKbdA11ySettings kbd_a11y_settings;
86 };
87 
88 typedef gboolean (* ConfigBoolMappingFunc) (MetaInputSettings  *input_settings,
89                                             ClutterInputDevice *device,
90                                             gboolean            value);
91 
92 typedef void (*ConfigBoolFunc)   (MetaInputSettings  *input_settings,
93                                   ClutterInputDevice *device,
94                                   gboolean            setting);
95 typedef void (*ConfigDoubleFunc) (MetaInputSettings  *input_settings,
96                                   ClutterInputDevice *device,
97                                   gdouble             value);
98 typedef void (*ConfigUintFunc)   (MetaInputSettings  *input_settings,
99                                   ClutterInputDevice *device,
100                                   guint               value);
101 
102 G_DEFINE_TYPE_WITH_PRIVATE (MetaInputSettings, meta_input_settings, G_TYPE_OBJECT)
103 
104 enum
105 {
106   KBD_A11Y_CHANGED,
107   N_SIGNALS
108 };
109 
110 static guint signals[N_SIGNALS] = { 0 };
111 
112 static GSList *
meta_input_settings_get_devices(MetaInputSettings * settings,ClutterInputDeviceType type)113 meta_input_settings_get_devices (MetaInputSettings      *settings,
114                                  ClutterInputDeviceType  type)
115 {
116   MetaInputSettingsPrivate *priv;
117   GList *l;
118   GSList *list = NULL;
119 
120   priv = meta_input_settings_get_instance_private (settings);
121 
122   for (l = priv->devices; l; l = l->next)
123     {
124       ClutterInputDevice *device = l->data;
125 
126       if (clutter_input_device_get_device_type (device) == type &&
127           clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_LOGICAL)
128         list = g_slist_prepend (list, device);
129     }
130 
131   return list;
132 }
133 
134 static void
meta_input_settings_dispose(GObject * object)135 meta_input_settings_dispose (GObject *object)
136 {
137   MetaInputSettings *settings = META_INPUT_SETTINGS (object);
138   MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (settings);
139 
140   g_clear_object (&priv->mouse_settings);
141   g_clear_object (&priv->touchpad_settings);
142   g_clear_object (&priv->trackball_settings);
143   g_clear_object (&priv->keyboard_settings);
144   g_clear_object (&priv->keyboard_a11y_settings);
145   g_clear_pointer (&priv->mappable_devices, g_hash_table_unref);
146   g_clear_pointer (&priv->current_tools, g_hash_table_unref);
147 
148   g_clear_pointer (&priv->two_finger_devices, g_hash_table_destroy);
149 
150   G_OBJECT_CLASS (meta_input_settings_parent_class)->dispose (object);
151 }
152 
153 static void
settings_device_set_bool_setting(MetaInputSettings * input_settings,ClutterInputDevice * device,ConfigBoolFunc func,gboolean enabled)154 settings_device_set_bool_setting (MetaInputSettings  *input_settings,
155                                   ClutterInputDevice *device,
156                                   ConfigBoolFunc      func,
157                                   gboolean            enabled)
158 {
159   func (input_settings, device, enabled);
160 }
161 
162 static void
settings_set_bool_setting(MetaInputSettings * input_settings,ClutterInputDeviceType type,ConfigBoolMappingFunc mapping_func,ConfigBoolFunc func,gboolean enabled)163 settings_set_bool_setting (MetaInputSettings      *input_settings,
164                            ClutterInputDeviceType  type,
165                            ConfigBoolMappingFunc   mapping_func,
166                            ConfigBoolFunc          func,
167                            gboolean                enabled)
168 {
169   GSList *devices, *l;
170 
171   devices = meta_input_settings_get_devices (input_settings, type);
172 
173   for (l = devices; l; l = l->next)
174     {
175       gboolean value = enabled;
176 
177       if (mapping_func)
178         value = mapping_func (input_settings, l->data, value);
179       settings_device_set_bool_setting (input_settings, l->data, func, value);
180     }
181 
182   g_slist_free (devices);
183 }
184 
185 static void
settings_device_set_double_setting(MetaInputSettings * input_settings,ClutterInputDevice * device,ConfigDoubleFunc func,gdouble value)186 settings_device_set_double_setting (MetaInputSettings  *input_settings,
187                                     ClutterInputDevice *device,
188                                     ConfigDoubleFunc    func,
189                                     gdouble             value)
190 {
191   func (input_settings, device, value);
192 }
193 
194 static void
settings_set_double_setting(MetaInputSettings * input_settings,ClutterInputDeviceType type,ConfigDoubleFunc func,gdouble value)195 settings_set_double_setting (MetaInputSettings      *input_settings,
196                              ClutterInputDeviceType  type,
197                              ConfigDoubleFunc        func,
198                              gdouble                 value)
199 {
200   GSList *devices, *d;
201 
202   devices = meta_input_settings_get_devices (input_settings, type);
203 
204   for (d = devices; d; d = d->next)
205     settings_device_set_double_setting (input_settings, d->data, func, value);
206 
207   g_slist_free (devices);
208 }
209 
210 static void
settings_device_set_uint_setting(MetaInputSettings * input_settings,ClutterInputDevice * device,ConfigUintFunc func,guint value)211 settings_device_set_uint_setting (MetaInputSettings  *input_settings,
212                                   ClutterInputDevice *device,
213                                   ConfigUintFunc      func,
214                                   guint               value)
215 {
216   (func) (input_settings, device, value);
217 }
218 
219 static void
settings_set_uint_setting(MetaInputSettings * input_settings,ClutterInputDeviceType type,ConfigUintFunc func,guint value)220 settings_set_uint_setting (MetaInputSettings      *input_settings,
221                            ClutterInputDeviceType  type,
222                            ConfigUintFunc          func,
223                            guint                   value)
224 {
225   GSList *devices, *d;
226 
227   devices = meta_input_settings_get_devices (input_settings, type);
228 
229   for (d = devices; d; d = d->next)
230     settings_device_set_uint_setting (input_settings, d->data, func, value);
231 
232   g_slist_free (devices);
233 }
234 
235 static void
update_touchpad_left_handed(MetaInputSettings * input_settings,ClutterInputDevice * device)236 update_touchpad_left_handed (MetaInputSettings  *input_settings,
237                              ClutterInputDevice *device)
238 {
239   MetaInputSettingsClass *input_settings_class;
240   GDesktopTouchpadHandedness handedness;
241   MetaInputSettingsPrivate *priv;
242   gboolean enabled = FALSE;
243 
244   if (device &&
245       clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
246     return;
247 
248   priv = meta_input_settings_get_instance_private (input_settings);
249   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
250   handedness = g_settings_get_enum (priv->touchpad_settings, "left-handed");
251 
252   switch (handedness)
253     {
254     case G_DESKTOP_TOUCHPAD_HANDEDNESS_RIGHT:
255       enabled = FALSE;
256       break;
257     case G_DESKTOP_TOUCHPAD_HANDEDNESS_LEFT:
258       enabled = TRUE;
259       break;
260     case G_DESKTOP_TOUCHPAD_HANDEDNESS_MOUSE:
261       enabled = g_settings_get_boolean (priv->mouse_settings, "left-handed");
262       break;
263     default:
264       g_assert_not_reached ();
265     }
266 
267   if (device)
268     {
269       settings_device_set_bool_setting (input_settings, device,
270                                         input_settings_class->set_left_handed,
271                                         enabled);
272     }
273   else
274     {
275       settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, NULL,
276                                  input_settings_class->set_left_handed,
277                                  enabled);
278     }
279 }
280 
281 static void
update_mouse_left_handed(MetaInputSettings * input_settings,ClutterInputDevice * device)282 update_mouse_left_handed (MetaInputSettings  *input_settings,
283                           ClutterInputDevice *device)
284 {
285   MetaInputSettingsClass *input_settings_class;
286   MetaInputSettingsPrivate *priv;
287   gboolean enabled;
288 
289   if (device &&
290       clutter_input_device_get_device_type (device) != CLUTTER_POINTER_DEVICE)
291     return;
292 
293   priv = meta_input_settings_get_instance_private (input_settings);
294   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
295   enabled = g_settings_get_boolean (priv->mouse_settings, "left-handed");
296 
297   if (device)
298     {
299       settings_device_set_bool_setting (input_settings, device,
300                                         input_settings_class->set_left_handed,
301                                         enabled);
302     }
303   else
304     {
305       GDesktopTouchpadHandedness touchpad_handedness;
306 
307       settings_set_bool_setting (input_settings, CLUTTER_POINTER_DEVICE, NULL,
308                                  input_settings_class->set_left_handed,
309                                  enabled);
310 
311       touchpad_handedness = g_settings_get_enum (priv->touchpad_settings,
312                                                  "left-handed");
313 
314       /* Also update touchpads if they're following mouse settings */
315       if (touchpad_handedness == G_DESKTOP_TOUCHPAD_HANDEDNESS_MOUSE)
316         update_touchpad_left_handed (input_settings, NULL);
317     }
318 }
319 
320 static void
do_update_pointer_accel_profile(MetaInputSettings * input_settings,GSettings * settings,ClutterInputDevice * device,GDesktopPointerAccelProfile profile)321 do_update_pointer_accel_profile (MetaInputSettings          *input_settings,
322                                  GSettings                  *settings,
323                                  ClutterInputDevice         *device,
324                                  GDesktopPointerAccelProfile profile)
325 {
326   MetaInputSettingsPrivate *priv =
327     meta_input_settings_get_instance_private (input_settings);
328   MetaInputSettingsClass *input_settings_class =
329     META_INPUT_SETTINGS_GET_CLASS (input_settings);
330 
331   if (settings == priv->mouse_settings)
332     input_settings_class->set_mouse_accel_profile (input_settings,
333                                                    device,
334                                                    profile);
335   else if (settings == priv->trackball_settings)
336     input_settings_class->set_trackball_accel_profile (input_settings,
337                                                        device,
338                                                        profile);
339 }
340 
341 static void
update_pointer_accel_profile(MetaInputSettings * input_settings,GSettings * settings,ClutterInputDevice * device)342 update_pointer_accel_profile (MetaInputSettings  *input_settings,
343                               GSettings          *settings,
344                               ClutterInputDevice *device)
345 {
346   GDesktopPointerAccelProfile profile;
347 
348   profile = g_settings_get_enum (settings, "accel-profile");
349 
350   if (device)
351     {
352       do_update_pointer_accel_profile (input_settings, settings,
353                                        device, profile);
354     }
355   else
356     {
357       MetaInputSettingsPrivate *priv =
358         meta_input_settings_get_instance_private (input_settings);
359       GList *l;
360 
361       for (l = priv->devices; l; l = l->next)
362         {
363           device = l->data;
364 
365           if (clutter_input_device_get_device_mode (device) ==
366               CLUTTER_INPUT_MODE_LOGICAL)
367             continue;
368 
369           do_update_pointer_accel_profile (input_settings, settings,
370                                            device, profile);
371         }
372     }
373 }
374 
375 static GSettings *
get_settings_for_device_type(MetaInputSettings * input_settings,ClutterInputDeviceType type)376 get_settings_for_device_type (MetaInputSettings      *input_settings,
377                               ClutterInputDeviceType  type)
378 {
379   MetaInputSettingsPrivate *priv;
380   priv = meta_input_settings_get_instance_private (input_settings);
381   switch (type)
382     {
383     case CLUTTER_POINTER_DEVICE:
384       return priv->mouse_settings;
385     case CLUTTER_TOUCHPAD_DEVICE:
386       return priv->touchpad_settings;
387     default:
388       return NULL;
389     }
390 }
391 
392 static void
update_middle_click_emulation(MetaInputSettings * input_settings,GSettings * settings,ClutterInputDevice * device)393 update_middle_click_emulation (MetaInputSettings  *input_settings,
394                                GSettings          *settings,
395                                ClutterInputDevice *device)
396 {
397   ConfigBoolFunc func;
398   const gchar *key = "middle-click-emulation";
399   MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings);
400 
401   if (!settings)
402     return;
403 
404   if (settings == priv->mouse_settings)
405     func = META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_mouse_middle_click_emulation;
406   else if (settings == priv->touchpad_settings)
407     func = META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_touchpad_middle_click_emulation;
408   else if (settings == priv->trackball_settings)
409     func = META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_trackball_middle_click_emulation;
410   else
411     return;
412 
413   if (device)
414     {
415       settings_device_set_bool_setting (input_settings, device, func,
416                                         g_settings_get_boolean (settings, key));
417     }
418   else
419     {
420       settings_set_bool_setting (input_settings, CLUTTER_POINTER_DEVICE,
421                                  NULL, func,
422                                  g_settings_get_boolean (settings, key));
423     }
424 }
425 
426 static void
update_device_speed(MetaInputSettings * input_settings,ClutterInputDevice * device)427 update_device_speed (MetaInputSettings      *input_settings,
428                      ClutterInputDevice     *device)
429 {
430   GSettings *settings;
431   ConfigDoubleFunc func;
432   const gchar *key = "speed";
433 
434   func = META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_speed;
435 
436   if (device)
437     {
438       settings = get_settings_for_device_type (input_settings,
439                                                clutter_input_device_get_device_type (device));
440       if (!settings)
441         return;
442 
443       settings_device_set_double_setting (input_settings, device, func,
444                                           g_settings_get_double (settings, key));
445     }
446   else
447     {
448       settings = get_settings_for_device_type (input_settings, CLUTTER_POINTER_DEVICE);
449       settings_set_double_setting (input_settings, CLUTTER_POINTER_DEVICE, func,
450                                    g_settings_get_double (settings, key));
451       settings = get_settings_for_device_type (input_settings, CLUTTER_TOUCHPAD_DEVICE);
452       settings_set_double_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, func,
453                                    g_settings_get_double (settings, key));
454     }
455 }
456 
457 static void
update_device_natural_scroll(MetaInputSettings * input_settings,ClutterInputDevice * device)458 update_device_natural_scroll (MetaInputSettings      *input_settings,
459                               ClutterInputDevice     *device)
460 {
461   GSettings *settings;
462   ConfigBoolFunc func;
463   const gchar *key = "natural-scroll";
464 
465   func = META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_invert_scroll;
466 
467   if (device)
468     {
469       settings = get_settings_for_device_type (input_settings,
470                                                clutter_input_device_get_device_type (device));
471       if (!settings)
472         return;
473 
474       settings_device_set_bool_setting (input_settings, device, func,
475                                         g_settings_get_boolean (settings, key));
476     }
477   else
478     {
479       settings = get_settings_for_device_type (input_settings, CLUTTER_POINTER_DEVICE);
480       settings_set_bool_setting (input_settings, CLUTTER_POINTER_DEVICE,
481                                  NULL, func,
482                                  g_settings_get_boolean (settings, key));
483       settings = get_settings_for_device_type (input_settings, CLUTTER_TOUCHPAD_DEVICE);
484       settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
485                                  NULL, func,
486                                  g_settings_get_boolean (settings, key));
487     }
488 }
489 
490 static void
update_touchpad_disable_while_typing(MetaInputSettings * input_settings,ClutterInputDevice * device)491 update_touchpad_disable_while_typing (MetaInputSettings  *input_settings,
492                                       ClutterInputDevice *device)
493 {
494   GSettings *settings;
495   MetaInputSettingsClass *input_settings_class;
496   MetaInputSettingsPrivate *priv;
497   gboolean enabled;
498   const gchar *key = "disable-while-typing";
499 
500   if (device &&
501       clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
502     return;
503 
504   priv = meta_input_settings_get_instance_private (input_settings);
505   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
506   enabled = g_settings_get_boolean (priv->touchpad_settings, key);
507 
508   if (device)
509    {
510       settings = get_settings_for_device_type (input_settings,
511                                                clutter_input_device_get_device_type (device));
512 
513       if (!settings)
514         return;
515 
516       settings_device_set_bool_setting (input_settings, device,
517                                         input_settings_class->set_disable_while_typing,
518                                         enabled);
519     }
520   else
521     {
522       settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, NULL,
523                                  input_settings_class->set_disable_while_typing,
524                                  enabled);
525     }
526 }
527 
528 static gboolean
device_is_tablet_touchpad(MetaInputSettings * input_settings,ClutterInputDevice * device)529 device_is_tablet_touchpad (MetaInputSettings  *input_settings,
530                            ClutterInputDevice *device)
531 {
532 #ifdef HAVE_LIBWACOM
533   WacomIntegrationFlags flags = 0;
534   WacomDevice *wacom_device;
535 
536   if (clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
537     return FALSE;
538 
539   wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (device));
540 
541   if (wacom_device)
542     {
543       flags = libwacom_get_integration_flags (wacom_device);
544 
545       if ((flags & (WACOM_DEVICE_INTEGRATED_SYSTEM |
546                     WACOM_DEVICE_INTEGRATED_DISPLAY)) == 0)
547         return TRUE;
548     }
549 #endif
550 
551   return FALSE;
552 }
553 
554 static gboolean
force_enable_on_tablet(MetaInputSettings * input_settings,ClutterInputDevice * device,gboolean value)555 force_enable_on_tablet (MetaInputSettings  *input_settings,
556                         ClutterInputDevice *device,
557                         gboolean            value)
558 {
559   return device_is_tablet_touchpad (input_settings, device) || value;
560 }
561 
562 static void
update_touchpad_tap_enabled(MetaInputSettings * input_settings,ClutterInputDevice * device)563 update_touchpad_tap_enabled (MetaInputSettings  *input_settings,
564                              ClutterInputDevice *device)
565 {
566   MetaInputSettingsClass *input_settings_class;
567   MetaInputSettingsPrivate *priv;
568   gboolean enabled;
569 
570   if (device &&
571       clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
572     return;
573 
574   priv = meta_input_settings_get_instance_private (input_settings);
575   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
576   enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-to-click");
577 
578   if (device)
579     {
580       enabled = force_enable_on_tablet (input_settings, device, enabled);
581       settings_device_set_bool_setting (input_settings, device,
582                                         input_settings_class->set_tap_enabled,
583                                         enabled);
584     }
585   else
586     {
587       settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
588                                  force_enable_on_tablet,
589                                  input_settings_class->set_tap_enabled,
590                                  enabled);
591     }
592 }
593 
594 static void
update_touchpad_tap_button_map(MetaInputSettings * input_settings,ClutterInputDevice * device)595 update_touchpad_tap_button_map (MetaInputSettings  *input_settings,
596                                 ClutterInputDevice *device)
597 {
598   MetaInputSettingsClass *input_settings_class;
599   GDesktopTouchpadTapButtonMap method;
600   MetaInputSettingsPrivate *priv;
601 
602   if (device &&
603       clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
604     return;
605 
606   priv = meta_input_settings_get_instance_private (input_settings);
607   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
608   method = g_settings_get_enum (priv->touchpad_settings, "tap-button-map");
609 
610   if (device)
611     {
612       settings_device_set_uint_setting (input_settings, device,
613                                         input_settings_class->set_tap_button_map,
614                                         method);
615     }
616   else
617     {
618       settings_set_uint_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
619                                  (ConfigUintFunc) input_settings_class->set_tap_button_map,
620                                  method);
621     }
622 }
623 
624 static void
update_touchpad_tap_and_drag_enabled(MetaInputSettings * input_settings,ClutterInputDevice * device)625 update_touchpad_tap_and_drag_enabled (MetaInputSettings  *input_settings,
626                                       ClutterInputDevice *device)
627 {
628   MetaInputSettingsClass *input_settings_class;
629   MetaInputSettingsPrivate *priv;
630   gboolean enabled;
631 
632   if (device &&
633       clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
634     return;
635 
636   priv = meta_input_settings_get_instance_private (input_settings);
637   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
638   enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-and-drag");
639 
640   if (device)
641     {
642       enabled = force_enable_on_tablet (input_settings, device, enabled);
643       settings_device_set_bool_setting (input_settings, device,
644                                         input_settings_class->set_tap_and_drag_enabled,
645                                         enabled);
646     }
647   else
648     {
649       settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
650                                  force_enable_on_tablet,
651                                  input_settings_class->set_tap_and_drag_enabled,
652                                  enabled);
653     }
654 }
655 
656 static void
update_touchpad_tap_and_drag_lock_enabled(MetaInputSettings * input_settings,ClutterInputDevice * device)657 update_touchpad_tap_and_drag_lock_enabled (MetaInputSettings  *input_settings,
658                                            ClutterInputDevice *device)
659 {
660   MetaInputSettingsClass *input_settings_class;
661   MetaInputSettingsPrivate *priv;
662   gboolean enabled;
663 
664   if (device &&
665       clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
666     return;
667 
668   priv = meta_input_settings_get_instance_private (input_settings);
669   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
670   enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-and-drag-lock");
671 
672   if (device)
673     {
674       settings_device_set_bool_setting (input_settings, device,
675                                         input_settings_class->set_tap_and_drag_lock_enabled,
676                                         enabled);
677     }
678   else
679     {
680       settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
681                                  NULL,
682                                  input_settings_class->set_tap_and_drag_lock_enabled,
683                                  enabled);
684     }
685 }
686 
687 static void
update_touchpad_edge_scroll(MetaInputSettings * input_settings,ClutterInputDevice * device)688 update_touchpad_edge_scroll (MetaInputSettings *input_settings,
689                              ClutterInputDevice *device)
690 {
691   MetaInputSettingsClass *input_settings_class;
692   gboolean edge_scroll_enabled;
693   gboolean two_finger_scroll_enabled;
694   gboolean two_finger_scroll_available;
695   MetaInputSettingsPrivate *priv;
696 
697   if (device &&
698       clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
699     return;
700 
701   priv = meta_input_settings_get_instance_private (input_settings);
702   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
703   edge_scroll_enabled = g_settings_get_boolean (priv->touchpad_settings, "edge-scrolling-enabled");
704   two_finger_scroll_enabled = g_settings_get_boolean (priv->touchpad_settings, "two-finger-scrolling-enabled");
705   two_finger_scroll_available = g_hash_table_size (priv->two_finger_devices) > 0;
706 
707   /* If both are enabled we prefer two finger. */
708   if (edge_scroll_enabled && two_finger_scroll_enabled && two_finger_scroll_available)
709     edge_scroll_enabled = FALSE;
710 
711   if (device)
712     {
713       settings_device_set_bool_setting (input_settings, device,
714                                         input_settings_class->set_edge_scroll,
715                                         edge_scroll_enabled);
716     }
717   else
718     {
719       settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, NULL,
720                                  (ConfigBoolFunc) input_settings_class->set_edge_scroll,
721                                  edge_scroll_enabled);
722     }
723 }
724 
725 static void
update_touchpad_two_finger_scroll(MetaInputSettings * input_settings,ClutterInputDevice * device)726 update_touchpad_two_finger_scroll (MetaInputSettings *input_settings,
727                                    ClutterInputDevice *device)
728 {
729   MetaInputSettingsClass *input_settings_class;
730   gboolean two_finger_scroll_enabled;
731   MetaInputSettingsPrivate *priv;
732 
733   if (device &&
734       clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
735     return;
736 
737   priv = meta_input_settings_get_instance_private (input_settings);
738   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
739   two_finger_scroll_enabled = g_settings_get_boolean (priv->touchpad_settings, "two-finger-scrolling-enabled");
740 
741   /* Disable edge since they can't both be set. */
742   if (two_finger_scroll_enabled)
743     update_touchpad_edge_scroll (input_settings, device);
744 
745   if (device)
746     {
747       settings_device_set_bool_setting (input_settings, device,
748                                         input_settings_class->set_two_finger_scroll,
749                                         two_finger_scroll_enabled);
750     }
751   else
752     {
753       settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, NULL,
754                                  (ConfigBoolFunc) input_settings_class->set_two_finger_scroll,
755                                  two_finger_scroll_enabled);
756     }
757 
758   /* Edge might have been disabled because two finger was on. */
759   if (!two_finger_scroll_enabled)
760     update_touchpad_edge_scroll (input_settings, device);
761 }
762 
763 static void
update_touchpad_click_method(MetaInputSettings * input_settings,ClutterInputDevice * device)764 update_touchpad_click_method (MetaInputSettings *input_settings,
765                               ClutterInputDevice *device)
766 {
767   MetaInputSettingsClass *input_settings_class;
768   GDesktopTouchpadClickMethod method;
769   MetaInputSettingsPrivate *priv;
770 
771   if (device &&
772       clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
773     return;
774 
775   priv = meta_input_settings_get_instance_private (input_settings);
776   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
777   method = g_settings_get_enum (priv->touchpad_settings, "click-method");
778 
779   if (device)
780     {
781       settings_device_set_uint_setting (input_settings, device,
782                                         input_settings_class->set_click_method,
783                                         method);
784     }
785   else
786     {
787       settings_set_uint_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
788                                  (ConfigUintFunc) input_settings_class->set_click_method,
789                                  method);
790     }
791 }
792 
793 static void
update_touchpad_send_events(MetaInputSettings * input_settings,ClutterInputDevice * device)794 update_touchpad_send_events (MetaInputSettings  *input_settings,
795                              ClutterInputDevice *device)
796 {
797   MetaInputSettingsClass *input_settings_class;
798   MetaInputSettingsPrivate *priv;
799   GDesktopDeviceSendEvents mode;
800 
801   if (device &&
802       clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
803     return;
804 
805   priv = meta_input_settings_get_instance_private (input_settings);
806   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
807   mode = g_settings_get_enum (priv->touchpad_settings, "send-events");
808 
809   if (device)
810     {
811       settings_device_set_uint_setting (input_settings, device,
812                                         input_settings_class->set_send_events,
813                                         mode);
814     }
815   else
816     {
817       settings_set_uint_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
818                                  input_settings_class->set_send_events,
819                                  mode);
820     }
821 }
822 
823 static void
update_trackball_scroll_button(MetaInputSettings * input_settings,ClutterInputDevice * device)824 update_trackball_scroll_button (MetaInputSettings  *input_settings,
825                                 ClutterInputDevice *device)
826 {
827   MetaInputSettingsClass *input_settings_class;
828   MetaInputSettingsPrivate *priv;
829   guint button;
830   gboolean button_lock;
831 
832   priv = meta_input_settings_get_instance_private (input_settings);
833   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
834 
835   if (device && !input_settings_class->is_trackball_device (input_settings, device))
836     return;
837 
838   /* This key is 'i' in the schema but it also specifies a minimum
839    * range of 0 so the cast here is safe. */
840   button = (guint) g_settings_get_int (priv->trackball_settings, "scroll-wheel-emulation-button");
841   button_lock = g_settings_get_boolean (priv->trackball_settings, "scroll-wheel-emulation-button-lock");
842 
843   if (device)
844     {
845       input_settings_class->set_scroll_button (input_settings, device, button, button_lock);
846     }
847   else if (!device)
848     {
849       GList *l;
850 
851       for (l = priv->devices; l; l = l->next)
852         {
853           device = l->data;
854 
855           if (input_settings_class->is_trackball_device (input_settings, device))
856             input_settings_class->set_scroll_button (input_settings, device, button, button_lock);
857         }
858     }
859 }
860 
861 static void
update_keyboard_repeat(MetaInputSettings * input_settings)862 update_keyboard_repeat (MetaInputSettings *input_settings)
863 {
864   MetaInputSettingsClass *input_settings_class;
865   MetaInputSettingsPrivate *priv;
866   guint delay, interval;
867   gboolean repeat;
868 
869   priv = meta_input_settings_get_instance_private (input_settings);
870   repeat = g_settings_get_boolean (priv->keyboard_settings, "repeat");
871   delay = g_settings_get_uint (priv->keyboard_settings, "delay");
872   interval = g_settings_get_uint (priv->keyboard_settings, "repeat-interval");
873 
874   delay = MAX (1, delay);
875   interval = MAX (1, interval);
876 
877   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
878   input_settings_class->set_keyboard_repeat (input_settings,
879                                              repeat, delay, interval);
880 }
881 
882 static void
update_tablet_keep_aspect(MetaInputSettings * input_settings,GSettings * settings,ClutterInputDevice * device)883 update_tablet_keep_aspect (MetaInputSettings  *input_settings,
884                            GSettings          *settings,
885                            ClutterInputDevice *device)
886 {
887   MetaInputSettingsPrivate *priv;
888   MetaInputSettingsClass *input_settings_class;
889   DeviceMappingInfo *info;
890   gboolean keep_aspect;
891   double aspect_ratio;
892 
893   if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
894       clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
895       clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE)
896     return;
897 
898   priv = meta_input_settings_get_instance_private (input_settings);
899 
900   info = g_hash_table_lookup (priv->mappable_devices, device);
901   if (!info)
902     return;
903 
904 #ifdef HAVE_LIBWACOM
905   {
906     WacomDevice *wacom_device;
907 
908     wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (device));
909 
910     /* Keep aspect only makes sense in external tablets */
911     if (wacom_device &&
912         libwacom_get_integration_flags (wacom_device) != WACOM_DEVICE_INTEGRATED_NONE)
913       return;
914   }
915 #endif
916 
917   keep_aspect = g_settings_get_boolean (settings, "keep-aspect");
918 
919   if (keep_aspect)
920     aspect_ratio = info->aspect_ratio;
921   else
922     aspect_ratio = 0;
923 
924   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
925   input_settings_class->set_tablet_aspect_ratio (input_settings, device, aspect_ratio);
926 }
927 
928 static void
update_tablet_mapping(MetaInputSettings * input_settings,GSettings * settings,ClutterInputDevice * device)929 update_tablet_mapping (MetaInputSettings  *input_settings,
930                        GSettings          *settings,
931                        ClutterInputDevice *device)
932 {
933   MetaInputSettingsClass *input_settings_class;
934   GDesktopTabletMapping mapping;
935 
936   if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
937       clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
938       clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE)
939     return;
940 
941 #ifdef HAVE_LIBWACOM
942   {
943     WacomDevice *wacom_device;
944 
945     wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (device));
946 
947     /* Tablet mapping only makes sense on external tablets */
948     if (wacom_device &&
949         (libwacom_get_integration_flags (wacom_device) != WACOM_DEVICE_INTEGRATED_NONE))
950       return;
951   }
952 #endif
953 
954   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
955   mapping = g_settings_get_enum (settings, "mapping");
956 
957   settings_device_set_uint_setting (input_settings, device,
958                                     input_settings_class->set_tablet_mapping,
959                                     mapping);
960 }
961 
962 static void
update_tablet_area(MetaInputSettings * input_settings,GSettings * settings,ClutterInputDevice * device)963 update_tablet_area (MetaInputSettings  *input_settings,
964                     GSettings          *settings,
965                     ClutterInputDevice *device)
966 {
967   MetaInputSettingsClass *input_settings_class;
968   GVariant *variant;
969   const gdouble *area;
970   gsize n_elems;
971 
972   if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
973       clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
974       clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE)
975     return;
976 
977 #ifdef HAVE_LIBWACOM
978   {
979     WacomDevice *wacom_device;
980 
981     wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (device));
982 
983     /* Tablet area only makes sense on system/display integrated tablets */
984     if (wacom_device &&
985         (libwacom_get_integration_flags (wacom_device) &
986          (WACOM_DEVICE_INTEGRATED_SYSTEM | WACOM_DEVICE_INTEGRATED_DISPLAY)) == 0)
987       return;
988   }
989 #endif
990 
991   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
992   variant = g_settings_get_value (settings, "area");
993 
994   area = g_variant_get_fixed_array (variant, &n_elems, sizeof (gdouble));
995   if (n_elems == 4)
996     {
997       input_settings_class->set_tablet_area (input_settings, device,
998                                              area[0], area[1],
999                                              area[2], area[3]);
1000     }
1001 
1002   g_variant_unref (variant);
1003 }
1004 
1005 static void
update_tablet_left_handed(MetaInputSettings * input_settings,GSettings * settings,ClutterInputDevice * device)1006 update_tablet_left_handed (MetaInputSettings  *input_settings,
1007                            GSettings          *settings,
1008                            ClutterInputDevice *device)
1009 {
1010   MetaInputSettingsClass *input_settings_class;
1011   gboolean enabled;
1012 
1013   if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
1014       clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
1015       clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE &&
1016       clutter_input_device_get_device_type (device) != CLUTTER_PAD_DEVICE)
1017     return;
1018 
1019 #ifdef HAVE_LIBWACOM
1020   {
1021     WacomDevice *wacom_device;
1022 
1023     wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (device));
1024 
1025     /* Left handed mode only makes sense on external tablets */
1026     if (wacom_device &&
1027         (libwacom_get_integration_flags (wacom_device) != WACOM_DEVICE_INTEGRATED_NONE))
1028       return;
1029   }
1030 #endif
1031 
1032   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
1033   enabled = g_settings_get_boolean (settings, "left-handed");
1034 
1035   settings_device_set_bool_setting (input_settings, device,
1036                                     input_settings_class->set_left_handed,
1037                                     enabled);
1038 }
1039 
1040 static void
meta_input_settings_changed_cb(GSettings * settings,const char * key,gpointer user_data)1041 meta_input_settings_changed_cb (GSettings  *settings,
1042                                 const char *key,
1043                                 gpointer    user_data)
1044 {
1045   MetaInputSettings *input_settings = META_INPUT_SETTINGS (user_data);
1046   MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings);
1047 
1048   if (settings == priv->mouse_settings)
1049     {
1050       if (strcmp (key, "left-handed") == 0)
1051         update_mouse_left_handed (input_settings, NULL);
1052       else if (strcmp (key, "speed") == 0)
1053         update_device_speed (input_settings, NULL);
1054       else if (strcmp (key, "natural-scroll") == 0)
1055         update_device_natural_scroll (input_settings, NULL);
1056       else if (strcmp (key, "accel-profile") == 0)
1057         update_pointer_accel_profile (input_settings, settings, NULL);
1058       else if (strcmp (key, "middle-click-emulation") == 0)
1059         update_middle_click_emulation (input_settings, settings, NULL);
1060     }
1061   else if (settings == priv->touchpad_settings)
1062     {
1063       if (strcmp (key, "left-handed") == 0)
1064         update_touchpad_left_handed (input_settings, NULL);
1065       else if (strcmp (key, "speed") == 0)
1066         update_device_speed (input_settings, NULL);
1067       else if (strcmp (key, "natural-scroll") == 0)
1068         update_device_natural_scroll (input_settings, NULL);
1069       else if (strcmp (key, "tap-to-click") == 0)
1070         update_touchpad_tap_enabled (input_settings, NULL);
1071       else if (strcmp (key, "tap-button-map") == 0)
1072         update_touchpad_tap_button_map (input_settings, NULL);
1073       else if (strcmp (key, "tap-and-drag") == 0)
1074         update_touchpad_tap_and_drag_enabled (input_settings, NULL);
1075       else if (strcmp (key, "tap-and-drag-lock") == 0)
1076         update_touchpad_tap_and_drag_lock_enabled (input_settings, NULL);
1077       else if (strcmp(key, "disable-while-typing") == 0)
1078         update_touchpad_disable_while_typing (input_settings, NULL);
1079       else if (strcmp (key, "send-events") == 0)
1080         update_touchpad_send_events (input_settings, NULL);
1081       else if (strcmp (key, "edge-scrolling-enabled") == 0)
1082         update_touchpad_edge_scroll (input_settings, NULL);
1083       else if (strcmp (key, "two-finger-scrolling-enabled") == 0)
1084         update_touchpad_two_finger_scroll (input_settings, NULL);
1085       else if (strcmp (key, "click-method") == 0)
1086         update_touchpad_click_method (input_settings, NULL);
1087       else if (strcmp (key, "middle-click-emulation") == 0)
1088         update_middle_click_emulation (input_settings, settings, NULL);
1089     }
1090   else if (settings == priv->trackball_settings)
1091     {
1092       if (strcmp (key, "scroll-wheel-emulation-button") == 0 ||
1093           strcmp (key, "scroll-wheel-emulation-button-lock") == 0)
1094         update_trackball_scroll_button (input_settings, NULL);
1095       else if (strcmp (key, "accel-profile") == 0)
1096         update_pointer_accel_profile (input_settings, settings, NULL);
1097       else if (strcmp (key, "middle-click-emulation") == 0)
1098         update_middle_click_emulation (input_settings, settings, NULL);
1099     }
1100   else if (settings == priv->keyboard_settings)
1101     {
1102       if (strcmp (key, "repeat") == 0 ||
1103           strcmp (key, "repeat-interval") == 0 ||
1104           strcmp (key, "delay") == 0)
1105         update_keyboard_repeat (input_settings);
1106     }
1107 }
1108 
1109 static void
mapped_device_changed_cb(GSettings * settings,const gchar * key,DeviceMappingInfo * info)1110 mapped_device_changed_cb (GSettings         *settings,
1111                           const gchar       *key,
1112                           DeviceMappingInfo *info)
1113 {
1114   if (strcmp (key, "mapping") == 0)
1115     update_tablet_mapping (info->input_settings, settings, info->device);
1116   else if (strcmp (key, "area") == 0)
1117     update_tablet_area (info->input_settings, settings, info->device);
1118   else if (strcmp (key, "keep-aspect") == 0)
1119     update_tablet_keep_aspect (info->input_settings, settings, info->device);
1120   else if (strcmp (key, "left-handed") == 0)
1121     update_tablet_left_handed (info->input_settings, settings, info->device);
1122 }
1123 
1124 static void
apply_mappable_device_settings(MetaInputSettings * input_settings,DeviceMappingInfo * info)1125 apply_mappable_device_settings (MetaInputSettings *input_settings,
1126                                 DeviceMappingInfo *info)
1127 {
1128   ClutterInputDeviceType device_type;
1129 
1130   device_type = clutter_input_device_get_device_type (info->device);
1131 
1132   if (device_type == CLUTTER_TABLET_DEVICE ||
1133       device_type == CLUTTER_PEN_DEVICE ||
1134       device_type == CLUTTER_ERASER_DEVICE ||
1135       device_type == CLUTTER_PAD_DEVICE)
1136     {
1137       update_tablet_mapping (input_settings, info->settings, info->device);
1138       update_tablet_area (input_settings, info->settings, info->device);
1139       update_tablet_keep_aspect (input_settings, info->settings, info->device);
1140       update_tablet_left_handed (input_settings, info->settings, info->device);
1141     }
1142 }
1143 
1144 struct _keyboard_a11y_settings_flags_pair {
1145   const char *name;
1146   MetaKeyboardA11yFlags flag;
1147 } keyboard_a11y_settings_flags_pair[] = {
1148   { "enable",                    META_A11Y_KEYBOARD_ENABLED },
1149   { "timeout-enable",            META_A11Y_TIMEOUT_ENABLED },
1150   { "mousekeys-enable",          META_A11Y_MOUSE_KEYS_ENABLED },
1151   { "slowkeys-enable",           META_A11Y_SLOW_KEYS_ENABLED },
1152   { "slowkeys-beep-press",       META_A11Y_SLOW_KEYS_BEEP_PRESS },
1153   { "slowkeys-beep-accept",      META_A11Y_SLOW_KEYS_BEEP_ACCEPT },
1154   { "slowkeys-beep-reject",      META_A11Y_SLOW_KEYS_BEEP_REJECT },
1155   { "bouncekeys-enable",         META_A11Y_BOUNCE_KEYS_ENABLED },
1156   { "bouncekeys-beep-reject",    META_A11Y_BOUNCE_KEYS_BEEP_REJECT },
1157   { "togglekeys-enable",         META_A11Y_TOGGLE_KEYS_ENABLED },
1158   { "stickykeys-enable",         META_A11Y_STICKY_KEYS_ENABLED },
1159   { "stickykeys-modifier-beep",  META_A11Y_STICKY_KEYS_BEEP },
1160   { "stickykeys-two-key-off",    META_A11Y_STICKY_KEYS_TWO_KEY_OFF },
1161   { "feature-state-change-beep", META_A11Y_FEATURE_STATE_CHANGE_BEEP },
1162 };
1163 
1164 static void
load_keyboard_a11y_settings(MetaInputSettings * input_settings)1165 load_keyboard_a11y_settings (MetaInputSettings *input_settings)
1166 {
1167   MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings);
1168   MetaKbdA11ySettings kbd_a11y_settings = { 0 };
1169   guint i;
1170 
1171   kbd_a11y_settings.controls = 0;
1172   for (i = 0; i < G_N_ELEMENTS (keyboard_a11y_settings_flags_pair); i++)
1173     {
1174       if (g_settings_get_boolean (priv->keyboard_a11y_settings, keyboard_a11y_settings_flags_pair[i].name))
1175         kbd_a11y_settings.controls |= keyboard_a11y_settings_flags_pair[i].flag;
1176     }
1177 
1178   kbd_a11y_settings.timeout_delay = g_settings_get_int (priv->keyboard_a11y_settings,
1179                                                         "disable-timeout");
1180   kbd_a11y_settings.slowkeys_delay = g_settings_get_int (priv->keyboard_a11y_settings,
1181                                                          "slowkeys-delay");
1182   kbd_a11y_settings.debounce_delay = g_settings_get_int (priv->keyboard_a11y_settings,
1183                                                          "bouncekeys-delay");
1184   kbd_a11y_settings.mousekeys_init_delay = g_settings_get_int (priv->keyboard_a11y_settings,
1185                                                                "mousekeys-init-delay");
1186   kbd_a11y_settings.mousekeys_max_speed = g_settings_get_int (priv->keyboard_a11y_settings,
1187                                                               "mousekeys-max-speed");
1188   kbd_a11y_settings.mousekeys_accel_time = g_settings_get_int (priv->keyboard_a11y_settings,
1189                                                                "mousekeys-accel-time");
1190 
1191   priv->kbd_a11y_settings = kbd_a11y_settings;
1192   g_signal_emit (input_settings, signals[KBD_A11Y_CHANGED], 0, &priv->kbd_a11y_settings);
1193 }
1194 
1195 void
meta_input_settings_notify_kbd_a11y_change(MetaInputSettings * input_settings,MetaKeyboardA11yFlags new_flags,MetaKeyboardA11yFlags what_changed)1196 meta_input_settings_notify_kbd_a11y_change (MetaInputSettings     *input_settings,
1197                                             MetaKeyboardA11yFlags  new_flags,
1198                                             MetaKeyboardA11yFlags  what_changed)
1199 {
1200   MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings);
1201   guint i;
1202 
1203   for (i = 0; i < G_N_ELEMENTS (keyboard_a11y_settings_flags_pair); i++)
1204     {
1205       if (keyboard_a11y_settings_flags_pair[i].flag & what_changed)
1206         g_settings_set_boolean (priv->keyboard_a11y_settings,
1207                                 keyboard_a11y_settings_flags_pair[i].name,
1208                                 (new_flags & keyboard_a11y_settings_flags_pair[i].flag) ? TRUE : FALSE);
1209     }
1210 }
1211 
1212 static void
meta_input_keyboard_a11y_settings_changed(GSettings * settings,const char * key,gpointer user_data)1213 meta_input_keyboard_a11y_settings_changed (GSettings  *settings,
1214                                            const char *key,
1215                                            gpointer    user_data)
1216 {
1217   MetaInputSettings *input_settings = META_INPUT_SETTINGS (user_data);
1218 
1219   load_keyboard_a11y_settings (input_settings);
1220 }
1221 
1222 static GSettings *
lookup_device_settings(ClutterInputDevice * device)1223 lookup_device_settings (ClutterInputDevice *device)
1224 {
1225   const gchar *group, *schema, *vendor, *product;
1226   ClutterInputDeviceType type;
1227   GSettings *settings;
1228   gchar *path;
1229 
1230   type = clutter_input_device_get_device_type (device);
1231 
1232   if (type == CLUTTER_TOUCHSCREEN_DEVICE)
1233     {
1234       group = "touchscreens";
1235       schema = "org.gnome.desktop.peripherals.touchscreen";
1236     }
1237   else if (type == CLUTTER_TABLET_DEVICE ||
1238            type == CLUTTER_PEN_DEVICE ||
1239            type == CLUTTER_ERASER_DEVICE ||
1240            type == CLUTTER_CURSOR_DEVICE ||
1241            type == CLUTTER_PAD_DEVICE)
1242     {
1243       group = "tablets";
1244       schema = "org.gnome.desktop.peripherals.tablet";
1245     }
1246   else
1247     return NULL;
1248 
1249   vendor = clutter_input_device_get_vendor_id (device);
1250   product = clutter_input_device_get_product_id (device);
1251   path = g_strdup_printf ("/org/gnome/desktop/peripherals/%s/%s:%s/",
1252                           group, vendor, product);
1253 
1254   settings = g_settings_new_with_path (schema, path);
1255   g_free (path);
1256 
1257   return settings;
1258 }
1259 
1260 static GSettings *
lookup_tool_settings(ClutterInputDeviceTool * tool,ClutterInputDevice * device)1261 lookup_tool_settings (ClutterInputDeviceTool *tool,
1262                       ClutterInputDevice     *device)
1263 {
1264   GSettings *tool_settings;
1265   guint64 serial;
1266   gchar *path;
1267 
1268   tool_settings = g_object_get_qdata (G_OBJECT (tool), quark_tool_settings);
1269   if (tool_settings)
1270     return tool_settings;
1271 
1272   serial = clutter_input_device_tool_get_serial (tool);
1273 
1274   /* The Wacom driver uses serial 1 for serial-less devices but 1 is not a
1275    * real serial, so let's custom-case this */
1276   if (serial == 0 || serial == 1)
1277     {
1278       path = g_strdup_printf ("/org/gnome/desktop/peripherals/stylus/default-%s:%s/",
1279                               clutter_input_device_get_vendor_id (device),
1280                               clutter_input_device_get_product_id (device));
1281     }
1282   else
1283     {
1284       path = g_strdup_printf ("/org/gnome/desktop/peripherals/stylus/%" G_GINT64_MODIFIER "x/",
1285                               serial);
1286     }
1287 
1288   tool_settings =
1289     g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet.stylus",
1290                               path);
1291   g_object_set_qdata_full (G_OBJECT (tool), quark_tool_settings, tool_settings,
1292                            (GDestroyNotify) g_object_unref);
1293   g_free (path);
1294 
1295   return tool_settings;
1296 }
1297 
1298 static void
device_mapping_info_free(DeviceMappingInfo * info)1299 device_mapping_info_free (DeviceMappingInfo *info)
1300 {
1301   g_clear_signal_handler (&info->changed_id, info->settings);
1302   g_object_unref (info->settings);
1303   g_free (info->group_modes);
1304   g_free (info);
1305 }
1306 
1307 static gboolean
check_add_mappable_device(MetaInputSettings * input_settings,ClutterInputDevice * device)1308 check_add_mappable_device (MetaInputSettings  *input_settings,
1309                            ClutterInputDevice *device)
1310 {
1311   MetaInputSettingsPrivate *priv;
1312   DeviceMappingInfo *info;
1313   ClutterInputDeviceType device_type;
1314   GSettings *settings;
1315 
1316   device_type = clutter_input_device_get_device_type (device);
1317 
1318   if ((device_type == CLUTTER_TABLET_DEVICE ||
1319        device_type == CLUTTER_PEN_DEVICE ||
1320        device_type == CLUTTER_ERASER_DEVICE ||
1321        device_type == CLUTTER_PAD_DEVICE) &&
1322       g_getenv ("MUTTER_DISABLE_WACOM_CONFIGURATION") != NULL)
1323     return FALSE;
1324 
1325   settings = lookup_device_settings (device);
1326 
1327   if (!settings)
1328     return FALSE;
1329 
1330   priv = meta_input_settings_get_instance_private (input_settings);
1331 
1332   info = g_new0 (DeviceMappingInfo, 1);
1333   info->input_settings = input_settings;
1334   info->device = device;
1335   info->settings = settings;
1336 
1337   if (device_type == CLUTTER_PAD_DEVICE)
1338     {
1339       info->group_modes =
1340         g_new0 (guint, clutter_input_device_get_n_mode_groups (device));
1341     }
1342 
1343   info->changed_id = g_signal_connect (settings, "changed",
1344                                        G_CALLBACK (mapped_device_changed_cb),
1345                                        info);
1346 
1347   g_hash_table_insert (priv->mappable_devices, device, info);
1348 
1349   apply_mappable_device_settings (input_settings, info);
1350 
1351   return TRUE;
1352 }
1353 
1354 static void
apply_device_settings(MetaInputSettings * input_settings,ClutterInputDevice * device)1355 apply_device_settings (MetaInputSettings  *input_settings,
1356                        ClutterInputDevice *device)
1357 {
1358   MetaInputSettingsPrivate *priv =
1359     meta_input_settings_get_instance_private (input_settings);
1360 
1361   update_device_speed (input_settings, device);
1362   update_device_natural_scroll (input_settings, device);
1363 
1364   update_mouse_left_handed (input_settings, device);
1365   update_pointer_accel_profile (input_settings,
1366                                 priv->mouse_settings,
1367                                 device);
1368 
1369   update_touchpad_left_handed (input_settings, device);
1370   update_touchpad_tap_enabled (input_settings, device);
1371   update_touchpad_tap_button_map (input_settings, device);
1372   update_touchpad_tap_and_drag_enabled (input_settings, device);
1373   update_touchpad_tap_and_drag_lock_enabled (input_settings, device);
1374   update_touchpad_disable_while_typing (input_settings, device);
1375   update_touchpad_send_events (input_settings, device);
1376   update_touchpad_two_finger_scroll (input_settings, device);
1377   update_touchpad_edge_scroll (input_settings, device);
1378   update_touchpad_click_method (input_settings, device);
1379 
1380   update_trackball_scroll_button (input_settings, device);
1381   update_pointer_accel_profile (input_settings,
1382                                 priv->trackball_settings,
1383                                 device);
1384 
1385   update_middle_click_emulation (input_settings, priv->mouse_settings, device);
1386   update_middle_click_emulation (input_settings, priv->touchpad_settings, device);
1387   update_middle_click_emulation (input_settings, priv->trackball_settings, device);
1388 }
1389 
1390 static void
update_stylus_pressure(MetaInputSettings * input_settings,ClutterInputDevice * device,ClutterInputDeviceTool * tool)1391 update_stylus_pressure (MetaInputSettings      *input_settings,
1392                         ClutterInputDevice     *device,
1393                         ClutterInputDeviceTool *tool)
1394 {
1395   MetaInputSettingsClass *input_settings_class;
1396   GSettings *tool_settings;
1397   const gint32 *curve;
1398   GVariant *variant;
1399   gsize n_elems;
1400 
1401   if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
1402       clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
1403       clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE)
1404     return;
1405 
1406   if (!tool)
1407     return;
1408 
1409   tool_settings = lookup_tool_settings (tool, device);
1410 
1411   if (clutter_input_device_tool_get_tool_type (tool) ==
1412       CLUTTER_INPUT_DEVICE_TOOL_ERASER)
1413     variant = g_settings_get_value (tool_settings, "eraser-pressure-curve");
1414   else
1415     variant = g_settings_get_value (tool_settings, "pressure-curve");
1416 
1417   curve = g_variant_get_fixed_array (variant, &n_elems, sizeof (gint32));
1418   if (n_elems != 4)
1419     return;
1420 
1421   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
1422   input_settings_class->set_stylus_pressure (input_settings, device, tool, curve);
1423 }
1424 
1425 static void
update_stylus_buttonmap(MetaInputSettings * input_settings,ClutterInputDevice * device,ClutterInputDeviceTool * tool)1426 update_stylus_buttonmap (MetaInputSettings      *input_settings,
1427                          ClutterInputDevice     *device,
1428                          ClutterInputDeviceTool *tool)
1429 {
1430   MetaInputSettingsClass *input_settings_class;
1431   GDesktopStylusButtonAction primary, secondary, tertiary;
1432   GSettings *tool_settings;
1433 
1434   if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
1435       clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
1436       clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE)
1437     return;
1438 
1439   if (!tool)
1440     return;
1441 
1442   tool_settings = lookup_tool_settings (tool, device);
1443 
1444   primary = g_settings_get_enum (tool_settings, "button-action");
1445   secondary = g_settings_get_enum (tool_settings, "secondary-button-action");
1446   tertiary = g_settings_get_enum (tool_settings, "tertiary-button-action");
1447 
1448   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
1449   input_settings_class->set_stylus_button_map (input_settings, device, tool,
1450                                                primary, secondary, tertiary);
1451 }
1452 
1453 static void
apply_stylus_settings(MetaInputSettings * input_settings,ClutterInputDevice * device,ClutterInputDeviceTool * tool)1454 apply_stylus_settings (MetaInputSettings      *input_settings,
1455                        ClutterInputDevice     *device,
1456                        ClutterInputDeviceTool *tool)
1457 {
1458   update_stylus_pressure (input_settings, device, tool);
1459   update_stylus_buttonmap (input_settings, device, tool);
1460 }
1461 
1462 static void
evaluate_two_finger_scrolling(MetaInputSettings * input_settings,ClutterInputDevice * device)1463 evaluate_two_finger_scrolling (MetaInputSettings  *input_settings,
1464                                ClutterInputDevice *device)
1465 {
1466   MetaInputSettingsClass *klass;
1467   MetaInputSettingsPrivate *priv;
1468 
1469   if (clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
1470     return;
1471 
1472   klass = META_INPUT_SETTINGS_GET_CLASS (input_settings);
1473   priv = meta_input_settings_get_instance_private (input_settings);
1474 
1475   if (klass->has_two_finger_scroll (input_settings, device))
1476     g_hash_table_add (priv->two_finger_devices, device);
1477 }
1478 
1479 void
meta_input_settings_add_device(MetaInputSettings * input_settings,ClutterInputDevice * device)1480 meta_input_settings_add_device (MetaInputSettings  *input_settings,
1481                                 ClutterInputDevice *device)
1482 {
1483   MetaInputSettingsPrivate *priv =
1484     meta_input_settings_get_instance_private (input_settings);
1485 
1486   if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_LOGICAL)
1487     return;
1488 
1489   priv->devices = g_list_prepend (priv->devices, device);
1490   evaluate_two_finger_scrolling (input_settings, device);
1491 
1492   apply_device_settings (input_settings, device);
1493   check_add_mappable_device (input_settings, device);
1494 }
1495 
1496 void
meta_input_settings_remove_device(MetaInputSettings * input_settings,ClutterInputDevice * device)1497 meta_input_settings_remove_device (MetaInputSettings  *input_settings,
1498                                    ClutterInputDevice *device)
1499 {
1500   MetaInputSettingsPrivate *priv;
1501 
1502   priv = meta_input_settings_get_instance_private (input_settings);
1503   g_hash_table_remove (priv->mappable_devices, device);
1504   g_hash_table_remove (priv->current_tools, device);
1505 
1506   if (g_hash_table_remove (priv->two_finger_devices, device) &&
1507       g_hash_table_size (priv->two_finger_devices) == 0)
1508     apply_device_settings (input_settings, NULL);
1509 
1510   priv->devices = g_list_remove (priv->devices, device);
1511 }
1512 
1513 static void
current_tool_changed_cb(GSettings * settings,const char * key,gpointer user_data)1514 current_tool_changed_cb (GSettings  *settings,
1515                          const char *key,
1516                          gpointer    user_data)
1517 {
1518   CurrentToolInfo *info = user_data;
1519 
1520   apply_stylus_settings (info->input_settings, info->device, info->tool);
1521 }
1522 
1523 static CurrentToolInfo *
current_tool_info_new(MetaInputSettings * input_settings,ClutterInputDevice * device,ClutterInputDeviceTool * tool)1524 current_tool_info_new (MetaInputSettings      *input_settings,
1525                        ClutterInputDevice     *device,
1526                        ClutterInputDeviceTool *tool)
1527 {
1528   CurrentToolInfo *info;
1529 
1530   info = g_new0 (CurrentToolInfo, 1);
1531   info->input_settings = input_settings;
1532   info->device = device;
1533   info->tool = tool;
1534   info->settings = lookup_tool_settings (tool, device);
1535   info->changed_id =
1536     g_signal_connect (info->settings, "changed",
1537                       G_CALLBACK (current_tool_changed_cb),
1538                       info);
1539   return info;
1540 }
1541 
1542 static void
current_tool_info_free(CurrentToolInfo * info)1543 current_tool_info_free (CurrentToolInfo *info)
1544 {
1545   g_clear_signal_handler (&info->changed_id, info->settings);
1546   g_free (info);
1547 }
1548 
1549 void
meta_input_settings_notify_tool_change(MetaInputSettings * input_settings,ClutterInputDevice * device,ClutterInputDeviceTool * tool)1550 meta_input_settings_notify_tool_change (MetaInputSettings      *input_settings,
1551                                         ClutterInputDevice     *device,
1552                                         ClutterInputDeviceTool *tool)
1553 {
1554   MetaInputSettingsPrivate *priv;
1555 
1556   priv = meta_input_settings_get_instance_private (input_settings);
1557 
1558   if (tool)
1559     {
1560       CurrentToolInfo *current_tool;
1561 
1562       current_tool = current_tool_info_new (input_settings, device, tool);
1563       g_hash_table_insert (priv->current_tools, device, current_tool);
1564       apply_stylus_settings (input_settings, device, tool);
1565     }
1566   else
1567     {
1568       g_hash_table_remove (priv->current_tools, device);
1569     }
1570 }
1571 
1572 static void
check_mappable_devices(MetaInputSettings * input_settings)1573 check_mappable_devices (MetaInputSettings *input_settings)
1574 {
1575   MetaInputSettingsPrivate *priv;
1576   GList *l;
1577 
1578   priv = meta_input_settings_get_instance_private (input_settings);
1579 
1580   for (l = priv->devices; l; l = l->next)
1581     {
1582       ClutterInputDevice *device = l->data;
1583 
1584       if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_LOGICAL)
1585         continue;
1586 
1587       check_add_mappable_device (input_settings, device);
1588     }
1589 }
1590 
1591 static void
meta_input_settings_constructed(GObject * object)1592 meta_input_settings_constructed (GObject *object)
1593 {
1594   MetaInputSettings *input_settings = META_INPUT_SETTINGS (object);
1595   GSList *devices, *d;
1596 
1597   devices = meta_input_settings_get_devices (input_settings, CLUTTER_TOUCHPAD_DEVICE);
1598   for (d = devices; d; d = d->next)
1599     evaluate_two_finger_scrolling (input_settings, d->data);
1600 
1601   g_slist_free (devices);
1602 
1603   apply_device_settings (input_settings, NULL);
1604   update_keyboard_repeat (input_settings);
1605   check_mappable_devices (input_settings);
1606 
1607   load_keyboard_a11y_settings (input_settings);
1608 }
1609 
1610 static void
meta_input_settings_class_init(MetaInputSettingsClass * klass)1611 meta_input_settings_class_init (MetaInputSettingsClass *klass)
1612 {
1613   GObjectClass *object_class = G_OBJECT_CLASS (klass);
1614 
1615   object_class->dispose = meta_input_settings_dispose;
1616   object_class->constructed = meta_input_settings_constructed;
1617 
1618   quark_tool_settings =
1619     g_quark_from_static_string ("meta-input-settings-tool-settings");
1620 
1621   signals[KBD_A11Y_CHANGED] =
1622     g_signal_new ("kbd-a11y-changed",
1623                   G_TYPE_FROM_CLASS (object_class),
1624                   G_SIGNAL_RUN_LAST,
1625                   0, NULL, NULL, NULL,
1626                   G_TYPE_NONE, 1,
1627                   G_TYPE_POINTER);
1628 
1629 }
1630 
1631 static void
meta_input_settings_init(MetaInputSettings * settings)1632 meta_input_settings_init (MetaInputSettings *settings)
1633 {
1634   MetaInputSettingsPrivate *priv;
1635 
1636   priv = meta_input_settings_get_instance_private (settings);
1637 
1638   priv->mouse_settings = g_settings_new ("org.gnome.desktop.peripherals.mouse");
1639   g_signal_connect (priv->mouse_settings, "changed",
1640                     G_CALLBACK (meta_input_settings_changed_cb), settings);
1641 
1642   priv->touchpad_settings = g_settings_new ("org.gnome.desktop.peripherals.touchpad");
1643   g_signal_connect (priv->touchpad_settings, "changed",
1644                     G_CALLBACK (meta_input_settings_changed_cb), settings);
1645 
1646   priv->trackball_settings = g_settings_new ("org.gnome.desktop.peripherals.trackball");
1647   g_signal_connect (priv->trackball_settings, "changed",
1648                     G_CALLBACK (meta_input_settings_changed_cb), settings);
1649 
1650   priv->keyboard_settings = g_settings_new ("org.gnome.desktop.peripherals.keyboard");
1651   g_signal_connect (priv->keyboard_settings, "changed",
1652                     G_CALLBACK (meta_input_settings_changed_cb), settings);
1653 
1654   priv->keyboard_a11y_settings = g_settings_new ("org.gnome.desktop.a11y.keyboard");
1655   g_signal_connect (priv->keyboard_a11y_settings, "changed",
1656                     G_CALLBACK (meta_input_keyboard_a11y_settings_changed), settings);
1657 
1658   priv->mappable_devices =
1659     g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) device_mapping_info_free);
1660 
1661   priv->current_tools =
1662     g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) current_tool_info_free);
1663 
1664   priv->two_finger_devices = g_hash_table_new (NULL, NULL);
1665 }
1666 
1667 void
meta_input_settings_maybe_save_numlock_state(MetaInputSettings * input_settings,gboolean numlock_state)1668 meta_input_settings_maybe_save_numlock_state (MetaInputSettings *input_settings,
1669                                               gboolean           numlock_state)
1670 {
1671   MetaInputSettingsPrivate *priv;
1672 
1673   priv = meta_input_settings_get_instance_private (input_settings);
1674 
1675   if (!g_settings_get_boolean (priv->keyboard_settings, "remember-numlock-state"))
1676     return;
1677 
1678   if (numlock_state == g_settings_get_boolean (priv->keyboard_settings, "numlock-state"))
1679     return;
1680 
1681   g_settings_set_boolean (priv->keyboard_settings, "numlock-state", numlock_state);
1682 }
1683 
1684 gboolean
meta_input_settings_maybe_restore_numlock_state(MetaInputSettings * input_settings)1685 meta_input_settings_maybe_restore_numlock_state (MetaInputSettings *input_settings)
1686 {
1687   MetaInputSettingsPrivate *priv;
1688   gboolean numlock_state = FALSE;
1689 
1690   priv = meta_input_settings_get_instance_private (input_settings);
1691 
1692   if (g_settings_get_boolean (priv->keyboard_settings, "remember-numlock-state"))
1693     numlock_state = g_settings_get_boolean (priv->keyboard_settings, "numlock-state");
1694 
1695   return numlock_state;
1696 }
1697 
1698 void
meta_input_settings_set_device_matrix(MetaInputSettings * input_settings,ClutterInputDevice * device,float matrix[6])1699 meta_input_settings_set_device_matrix (MetaInputSettings  *input_settings,
1700                                        ClutterInputDevice *device,
1701                                        float               matrix[6])
1702 {
1703   g_return_if_fail (META_IS_INPUT_SETTINGS (input_settings));
1704   g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
1705 
1706   META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_matrix (input_settings,
1707                                                               device,
1708                                                               matrix);
1709 }
1710 
1711 void
meta_input_settings_set_device_enabled(MetaInputSettings * input_settings,ClutterInputDevice * device,gboolean enabled)1712 meta_input_settings_set_device_enabled (MetaInputSettings  *input_settings,
1713                                         ClutterInputDevice *device,
1714                                         gboolean            enabled)
1715 {
1716   GDesktopDeviceSendEvents mode;
1717 
1718   g_return_if_fail (META_IS_INPUT_SETTINGS (input_settings));
1719   g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
1720 
1721   mode = enabled ?
1722     G_DESKTOP_DEVICE_SEND_EVENTS_ENABLED :
1723     G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED;
1724 
1725   META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_send_events (input_settings,
1726                                                                    device,
1727                                                                    mode);
1728 }
1729 
1730 void
meta_input_settings_set_device_aspect_ratio(MetaInputSettings * input_settings,ClutterInputDevice * device,double aspect_ratio)1731 meta_input_settings_set_device_aspect_ratio (MetaInputSettings  *input_settings,
1732                                              ClutterInputDevice *device,
1733                                              double              aspect_ratio)
1734 {
1735   MetaInputSettingsPrivate *priv;
1736   DeviceMappingInfo *info;
1737 
1738   g_return_if_fail (META_IS_INPUT_SETTINGS (input_settings));
1739   g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
1740 
1741   priv = meta_input_settings_get_instance_private (input_settings);
1742 
1743   info = g_hash_table_lookup (priv->mappable_devices, device);
1744   if (!info)
1745     return;
1746 
1747   info->aspect_ratio = aspect_ratio;
1748   update_tablet_keep_aspect (input_settings, info->settings, device);
1749 }
1750 
1751 void
meta_input_settings_get_kbd_a11y_settings(MetaInputSettings * input_settings,MetaKbdA11ySettings * a11y_settings)1752 meta_input_settings_get_kbd_a11y_settings (MetaInputSettings   *input_settings,
1753                                            MetaKbdA11ySettings *a11y_settings)
1754 {
1755   MetaInputSettingsPrivate *priv;
1756 
1757   g_return_if_fail (META_IS_INPUT_SETTINGS (input_settings));
1758 
1759   priv = meta_input_settings_get_instance_private (input_settings);
1760 
1761   *a11y_settings = priv->kbd_a11y_settings;
1762 }
1763