From 74b9d46d7c9a6cd881fae4b9aef9218a2cb2726f Mon Sep 17 00:00:00 2001
From: Rohan Hendrik Jotz-Lean <rohan@rohanlean.de>
Date: Thu, 20 Jan 2022 18:54:27 +0100
Subject: [PATCH] input-settings: Apply pointing stick settings

Apply the pointing stick (TrackPoint) configuration -- speed,
acceleration profile, and scrolling method -- from the gsettings desktop
schema.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3089>
---
 src/backends/meta-input-settings-dummy.c      | 18 +++++
 src/backends/meta-input-settings-private.h    |  8 ++
 src/backends/meta-input-settings.c            | 76 ++++++++++++++++++-
 .../native/meta-input-settings-native.c       | 48 ++++++++++++
 src/backends/x11/meta-input-settings-x11.c    | 60 +++++++++++++++
 5 files changed, 209 insertions(+), 1 deletion(-)

diff --git a/src/backends/meta-input-settings-dummy.c b/src/backends/meta-input-settings-dummy.c
index eecd3cc37..870764e3c 100644
--- a/src/backends/meta-input-settings-dummy.c
+++ b/src/backends/meta-input-settings-dummy.c
@@ -222,6 +222,20 @@ meta_input_settings_dummy_set_trackball_middle_click_emulation (MetaInputSetting
 {
 }
 
+static void
+meta_input_settings_dummy_set_pointing_stick_scroll_method (MetaInputSettings                 *settings,
+                                                            ClutterInputDevice                *device,
+                                                            GDesktopPointingStickScrollMethod  method)
+{
+}
+
+static void
+meta_input_settings_dummy_set_pointing_stick_accel_profile (MetaInputSettings           *settings,
+                                                            ClutterInputDevice          *device,
+                                                            GDesktopPointerAccelProfile  profile)
+{
+}
+
 static gboolean
 meta_input_settings_dummy_has_two_finger_scroll (MetaInputSettings  *settings,
                                                  ClutterInputDevice *device)
@@ -281,6 +295,10 @@ meta_input_settings_dummy_class_init (MetaInputSettingsDummyClass *klass)
     meta_input_settings_dummy_set_touchpad_accel_profile;
   input_settings_class->set_trackball_accel_profile =
     meta_input_settings_dummy_set_trackball_accel_profile;
+  input_settings_class->set_pointing_stick_scroll_method =
+    meta_input_settings_dummy_set_pointing_stick_scroll_method;
+  input_settings_class->set_pointing_stick_accel_profile =
+    meta_input_settings_dummy_set_pointing_stick_accel_profile;
   input_settings_class->set_stylus_pressure =
     meta_input_settings_dummy_set_stylus_pressure;
   input_settings_class->set_stylus_button_map =
diff --git a/src/backends/meta-input-settings-private.h b/src/backends/meta-input-settings-private.h
index 21407021e..226b195bc 100644
--- a/src/backends/meta-input-settings-private.h
+++ b/src/backends/meta-input-settings-private.h
@@ -129,6 +129,12 @@ struct _MetaInputSettingsClass
   void (* set_trackball_accel_profile) (MetaInputSettings          *settings,
                                         ClutterInputDevice         *device,
                                         GDesktopPointerAccelProfile profile);
+  void (* set_pointing_stick_accel_profile) (MetaInputSettings           *settings,
+                                             ClutterInputDevice          *device,
+                                             GDesktopPointerAccelProfile  profile);
+  void (* set_pointing_stick_scroll_method) (MetaInputSettings                 *settings,
+                                             ClutterInputDevice                *device,
+                                             GDesktopPointingStickScrollMethod  profile);
 
   void (* set_stylus_pressure) (MetaInputSettings            *settings,
                                 ClutterInputDevice           *device,
@@ -153,6 +159,8 @@ struct _MetaInputSettingsClass
 
   gboolean (* has_two_finger_scroll) (MetaInputSettings  *settings,
                                       ClutterInputDevice *device);
+  gboolean (* is_pointing_stick_device) (MetaInputSettings  *settings,
+                                         ClutterInputDevice *device);
 };
 
 void meta_input_settings_maybe_save_numlock_state (MetaInputSettings *input_settings,
diff --git a/src/backends/meta-input-settings.c b/src/backends/meta-input-settings.c
index 9b8deabb3..1903c6ef3 100644
--- a/src/backends/meta-input-settings.c
+++ b/src/backends/meta-input-settings.c
@@ -85,6 +85,7 @@ struct _MetaInputSettingsPrivate
   GSettings *mouse_settings;
   GSettings *touchpad_settings;
   GSettings *trackball_settings;
+  GSettings *pointing_stick_settings;
   GSettings *keyboard_settings;
   GSettings *keyboard_a11y_settings;
 
@@ -177,6 +178,7 @@ meta_input_settings_dispose (GObject *object)
   g_clear_object (&priv->mouse_settings);
   g_clear_object (&priv->touchpad_settings);
   g_clear_object (&priv->trackball_settings);
+  g_clear_object (&priv->pointing_stick_settings);
   g_clear_object (&priv->keyboard_settings);
   g_clear_object (&priv->keyboard_a11y_settings);
   g_clear_pointer (&priv->mappable_devices, g_hash_table_unref);
@@ -396,6 +398,10 @@ do_update_pointer_accel_profile (MetaInputSettings          *input_settings,
     input_settings_class->set_trackball_accel_profile (input_settings,
                                                        device,
                                                        profile);
+  else if (settings == priv->pointing_stick_settings)
+    input_settings_class->set_pointing_stick_accel_profile (input_settings,
+                                                            device,
+                                                            profile);
 }
 
 static void
@@ -984,6 +990,51 @@ update_trackball_scroll_button (MetaInputSettings  *input_settings,
     }
 }
 
+static void
+update_pointing_stick_scroll_method (MetaInputSettings  *input_settings,
+                                     GSettings          *settings,
+                                     ClutterInputDevice *device)
+{
+  MetaInputSettingsPrivate *priv =
+    meta_input_settings_get_instance_private (input_settings);
+  MetaInputSettingsClass *input_settings_class;
+  GDesktopPointingStickScrollMethod method;
+  ClutterInputCapabilities caps;
+
+  method = g_settings_get_enum (settings, "scroll-method");
+  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
+
+  if (device)
+    {
+      caps = clutter_input_device_get_capabilities (device);
+
+      if ((caps & CLUTTER_INPUT_CAPABILITY_TRACKPOINT) == 0)
+        return;
+    }
+
+  if (device)
+    {
+      input_settings_class->set_pointing_stick_scroll_method (input_settings, device, method);
+    }
+  else if (!device)
+    {
+      GList *l;
+
+      for (l = priv->devices; l; l = l->next)
+        {
+          device = l->data;
+          caps = clutter_input_device_get_capabilities (device);
+
+          if ((caps & CLUTTER_INPUT_CAPABILITY_TRACKPOINT) != 0)
+            {
+              input_settings_class->set_pointing_stick_scroll_method (input_settings,
+                                                                      device,
+                                                                      method);
+            }
+        }
+    }
+}
+
 static void
 update_keyboard_repeat (MetaInputSettings *input_settings)
 {
@@ -1172,7 +1223,7 @@ meta_input_settings_changed_cb (GSettings  *settings,
         update_touchpad_tap_and_drag_enabled (input_settings, NULL);
       else if (strcmp (key, "tap-and-drag-lock") == 0)
         update_touchpad_tap_and_drag_lock_enabled (input_settings, NULL);
-      else if (strcmp(key, "disable-while-typing") == 0)
+      else if (strcmp (key, "disable-while-typing") == 0)
         update_touchpad_disable_while_typing (input_settings, NULL);
       else if (strcmp (key, "send-events") == 0)
         update_touchpad_send_events (input_settings, NULL);
@@ -1195,6 +1246,15 @@ meta_input_settings_changed_cb (GSettings  *settings,
       else if (strcmp (key, "middle-click-emulation") == 0)
         update_middle_click_emulation (input_settings, settings, NULL);
     }
+  else if (settings == priv->pointing_stick_settings)
+    {
+      if (strcmp (key, "speed") == 0)
+        update_device_speed (input_settings, NULL);
+      else if (strcmp (key, "accel-profile") == 0)
+        update_pointer_accel_profile (input_settings, settings, NULL);
+      else if (strcmp (key, "scroll-method") == 0)
+        update_pointing_stick_scroll_method (input_settings, settings, NULL);
+    }
   else if (settings == priv->keyboard_settings)
     {
       if (strcmp (key, "repeat") == 0 ||
@@ -1478,6 +1538,16 @@ apply_device_settings (MetaInputSettings  *input_settings,
                                 priv->trackball_settings,
                                 device);
 
+  update_pointing_stick_scroll_method (input_settings,
+                                       priv->pointing_stick_settings,
+                                       device);
+
+  update_pointer_accel_profile (input_settings,
+                                priv->pointing_stick_settings,
+                                device);
+
+  load_keyboard_a11y_settings (input_settings);
+
   update_middle_click_emulation (input_settings, priv->mouse_settings, device);
   update_middle_click_emulation (input_settings, priv->touchpad_settings, device);
   update_middle_click_emulation (input_settings, priv->trackball_settings, device);
@@ -1773,6 +1843,10 @@ meta_input_settings_init (MetaInputSettings *settings)
   g_signal_connect (priv->trackball_settings, "changed",
                     G_CALLBACK (meta_input_settings_changed_cb), settings);
 
+  priv->pointing_stick_settings = g_settings_new ("org.gnome.desktop.peripherals.pointingstick");
+  g_signal_connect (priv->pointing_stick_settings, "changed",
+                    G_CALLBACK (meta_input_settings_changed_cb), settings);
+
   priv->keyboard_settings = g_settings_new ("org.gnome.desktop.peripherals.keyboard");
   g_signal_connect (priv->keyboard_settings, "changed",
                     G_CALLBACK (meta_input_settings_changed_cb), settings);
diff --git a/src/backends/native/meta-input-settings-native.c b/src/backends/native/meta-input-settings-native.c
index 1abf7e749..948c8696e 100644
--- a/src/backends/native/meta-input-settings-native.c
+++ b/src/backends/native/meta-input-settings-native.c
@@ -574,6 +574,52 @@ meta_input_settings_native_set_trackball_accel_profile (MetaInputSettings
   set_device_accel_profile (device, profile);
 }
 
+static void
+meta_input_settings_native_set_pointing_stick_accel_profile (MetaInputSettings           *settings,
+                                                             ClutterInputDevice          *device,
+                                                             GDesktopPointerAccelProfile  profile)
+{
+  ClutterInputCapabilities caps = clutter_input_device_get_capabilities (device);
+
+  if ((caps & CLUTTER_INPUT_CAPABILITY_TRACKPOINT) == 0)
+    return;
+
+  set_device_accel_profile (device, profile);
+}
+
+static void
+meta_input_settings_native_set_pointing_stick_scroll_method (MetaInputSettings                 *settings,
+                                                             ClutterInputDevice                *device,
+                                                             GDesktopPointingStickScrollMethod  method)
+{
+  ClutterInputCapabilities caps = clutter_input_device_get_capabilities (device);
+  struct libinput_device *libinput_device;
+  enum libinput_config_scroll_method libinput_method;
+
+  if ((caps & CLUTTER_INPUT_CAPABILITY_TRACKPOINT) == 0)
+    return;
+
+  libinput_device = meta_input_device_native_get_libinput_device (device);
+
+  switch (method)
+    {
+    case G_DESKTOP_POINTING_STICK_SCROLL_METHOD_DEFAULT:
+      libinput_method = libinput_device_config_scroll_get_default_method (libinput_device);
+      break;
+    case G_DESKTOP_POINTING_STICK_SCROLL_METHOD_NONE:
+      libinput_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
+      break;
+    case G_DESKTOP_POINTING_STICK_SCROLL_METHOD_ON_BUTTON_DOWN:
+      libinput_method = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
+      break;
+    default:
+      g_assert_not_reached ();
+      return;
+    }
+
+  device_set_scroll_method (libinput_device, libinput_method);
+}
+
 static void
 meta_input_settings_native_set_tablet_mapping (MetaInputSettings     *settings,
                                                ClutterInputDevice    *device,
@@ -803,6 +849,8 @@ meta_input_settings_native_class_init (MetaInputSettingsNativeClass *klass)
   input_settings_class->set_mouse_accel_profile = meta_input_settings_native_set_mouse_accel_profile;
   input_settings_class->set_touchpad_accel_profile = meta_input_settings_native_set_touchpad_accel_profile;
   input_settings_class->set_trackball_accel_profile = meta_input_settings_native_set_trackball_accel_profile;
+  input_settings_class->set_pointing_stick_accel_profile = meta_input_settings_native_set_pointing_stick_accel_profile;
+  input_settings_class->set_pointing_stick_scroll_method = meta_input_settings_native_set_pointing_stick_scroll_method;
 
   input_settings_class->set_stylus_pressure = meta_input_settings_native_set_stylus_pressure;
   input_settings_class->set_stylus_button_map = meta_input_settings_native_set_stylus_button_map;
diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c
index 0a2bbb23e..5abcb2461 100644
--- a/src/backends/x11/meta-input-settings-x11.c
+++ b/src/backends/x11/meta-input-settings-x11.c
@@ -595,6 +595,64 @@ meta_input_settings_x11_set_trackball_accel_profile (MetaInputSettings
   set_device_accel_profile (settings, device, profile);
 }
 
+static void
+meta_input_settings_x11_set_pointing_stick_accel_profile (MetaInputSettings           *settings,
+                                                          ClutterInputDevice          *device,
+                                                          GDesktopPointerAccelProfile  profile)
+{
+  ClutterInputCapabilities caps = clutter_input_device_get_capabilities (device);
+
+  if ((caps & CLUTTER_INPUT_CAPABILITY_TRACKPOINT) == 0)
+    return;
+
+  set_device_accel_profile (settings, device, profile);
+}
+
+static void
+meta_input_settings_x11_set_pointing_stick_scroll_method (MetaInputSettings                 *settings,
+                                                          ClutterInputDevice                *device,
+                                                          GDesktopPointingStickScrollMethod  method)
+{
+  ClutterInputCapabilities caps = clutter_input_device_get_capabilities (device);
+  guchar *defaults;
+  guchar values[3] = { 0 }; /* 2fg, edge, on-button */
+
+  if ((caps & CLUTTER_INPUT_CAPABILITY_TRACKPOINT) == 0)
+    return;
+
+  defaults = get_property (device, "libinput Scroll Method Enabled Default",
+                           XA_INTEGER, 8, 3);
+  if (!defaults)
+    return;
+
+  switch (method)
+    {
+    case G_DESKTOP_POINTING_STICK_SCROLL_METHOD_DEFAULT:
+      values[0] = defaults[0];
+      values[1] = defaults[1];
+      values[2] = defaults[2];
+      break;
+    case G_DESKTOP_POINTING_STICK_SCROLL_METHOD_NONE:
+      values[0] = 0;
+      values[1] = 0;
+      values[2] = 0;
+      break;
+    case G_DESKTOP_POINTING_STICK_SCROLL_METHOD_ON_BUTTON_DOWN:
+      values[0] = 0;
+      values[1] = 0;
+      values[2] = 1;
+      break;
+    default:
+      g_assert_not_reached ();
+      return;
+    }
+
+  change_property (settings, device, "libinput Scroll Method Enabled",
+                   XA_INTEGER, 8, &values, 3);
+
+  meta_XFree (defaults);
+}
+
 static void
 meta_input_settings_x11_set_tablet_mapping (MetaInputSettings     *settings,
                                             ClutterInputDevice    *device,
@@ -866,6 +924,8 @@ meta_input_settings_x11_class_init (MetaInputSettingsX11Class *klass)
   input_settings_class->set_mouse_accel_profile = meta_input_settings_x11_set_mouse_accel_profile;
   input_settings_class->set_touchpad_accel_profile = meta_input_settings_x11_set_touchpad_accel_profile;
   input_settings_class->set_trackball_accel_profile = meta_input_settings_x11_set_trackball_accel_profile;
+  input_settings_class->set_pointing_stick_accel_profile = meta_input_settings_x11_set_pointing_stick_accel_profile;
+  input_settings_class->set_pointing_stick_scroll_method = meta_input_settings_x11_set_pointing_stick_scroll_method;
 
   input_settings_class->set_stylus_pressure = meta_input_settings_x11_set_stylus_pressure;
   input_settings_class->set_stylus_button_map = meta_input_settings_x11_set_stylus_button_map;