Blame SOURCES/0001-backends-x11-Support-synaptics-configuration.patch

67f8b7
From 10b63b27ba84458884138cecc1b914b4f69bc9b9 Mon Sep 17 00:00:00 2001
67f8b7
From: Carlos Garnacho <carlosg@gnome.org>
67f8b7
Date: Thu, 19 Jan 2017 15:03:41 +0100
67f8b7
Subject: [PATCH] backends/x11: Support synaptics configuration
67f8b7
67f8b7
The code is taken mostly as-is from g-s-d, so we can drag the
67f8b7
dead horse a bit longer.
67f8b7
---
67f8b7
 src/backends/x11/meta-input-settings-x11.c | 264 +++++++++++++++++++++++++++++
67f8b7
 1 file changed, 264 insertions(+)
67f8b7
67f8b7
diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c
67f8b7
index 8f962b4..75ceb0c 100644
67f8b7
--- a/src/backends/x11/meta-input-settings-x11.c
67f8b7
+++ b/src/backends/x11/meta-input-settings-x11.c
67f8b7
@@ -26,6 +26,7 @@
67f8b7
 #include "meta-backend-x11.h"
67f8b7
 #include "meta-input-settings-x11.h"
67f8b7
 
67f8b7
+#include <stdlib.h>
67f8b7
 #include <string.h>
67f8b7
 #include <gdk/gdkx.h>
67f8b7
 #include <X11/Xatom.h>
67f8b7
@@ -118,6 +119,177 @@ change_property (ClutterInputDevice *device,
67f8b7
   meta_XFree (data_ret);
67f8b7
 }
67f8b7
 
67f8b7
+static gboolean
67f8b7
+is_device_synaptics (ClutterInputDevice *device)
67f8b7
+{
67f8b7
+  guchar *has_setting;
67f8b7
+
67f8b7
+  /* We just need looking for a synaptics-specific property */
67f8b7
+  has_setting = get_property (device, "Synaptics Off", XA_INTEGER, 8, 1);
67f8b7
+  if (!has_setting)
67f8b7
+    return FALSE;
67f8b7
+
67f8b7
+  meta_XFree (has_setting);
67f8b7
+  return TRUE;
67f8b7
+}
67f8b7
+
67f8b7
+static void
67f8b7
+change_synaptics_tap_left_handed (ClutterInputDevice *device,
67f8b7
+                                  gboolean            tap_enabled,
67f8b7
+                                  gboolean            left_handed)
67f8b7
+{
67f8b7
+  MetaDisplay *display = meta_get_display ();
67f8b7
+  MetaBackend *backend = meta_get_backend ();
67f8b7
+  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
67f8b7
+  XDevice *xdevice;
67f8b7
+  guchar *tap_action, *buttons;
67f8b7
+  guint buttons_capacity = 16, n_buttons;
67f8b7
+
67f8b7
+  xdevice = XOpenDevice(xdisplay, clutter_input_device_get_device_id (device));
67f8b7
+  if (!xdevice)
67f8b7
+    return;
67f8b7
+
67f8b7
+  tap_action = get_property (device, "Synaptics Tap Action",
67f8b7
+                             XA_INTEGER, 8, 7);
67f8b7
+  if (!tap_action)
67f8b7
+    goto out;
67f8b7
+
67f8b7
+  tap_action[4] = tap_enabled ? (left_handed ? 3 : 1) : 0;
67f8b7
+  tap_action[5] = tap_enabled ? (left_handed ? 1 : 3) : 0;
67f8b7
+  tap_action[6] = tap_enabled ? 2 : 0;
67f8b7
+
67f8b7
+  change_property (device, "Synaptics Tap Action",
67f8b7
+                   XA_INTEGER, 8, tap_action, 7);
67f8b7
+  meta_XFree (tap_action);
67f8b7
+
67f8b7
+  if (display)
67f8b7
+    meta_error_trap_push (display);
67f8b7
+  buttons = g_new (guchar, buttons_capacity);
67f8b7
+  n_buttons = XGetDeviceButtonMapping (xdisplay, xdevice,
67f8b7
+                                       buttons, buttons_capacity);
67f8b7
+
67f8b7
+  while (n_buttons > buttons_capacity)
67f8b7
+    {
67f8b7
+      buttons_capacity = n_buttons;
67f8b7
+      buttons = (guchar *) g_realloc (buttons,
67f8b7
+                                      buttons_capacity * sizeof (guchar));
67f8b7
+
67f8b7
+      n_buttons = XGetDeviceButtonMapping (xdisplay, xdevice,
67f8b7
+                                           buttons, buttons_capacity);
67f8b7
+    }
67f8b7
+
67f8b7
+  buttons[0] = left_handed ? 3 : 1;
67f8b7
+  buttons[2] = left_handed ? 1 : 3;
67f8b7
+  XSetDeviceButtonMapping (xdisplay, xdevice, buttons, n_buttons);
67f8b7
+
67f8b7
+  if (display && meta_error_trap_pop_with_return (display))
67f8b7
+    {
67f8b7
+      g_warning ("Could not set synaptics touchpad left-handed for %s",
67f8b7
+                 clutter_input_device_get_device_name (device));
67f8b7
+    }
67f8b7
+
67f8b7
+ out:
67f8b7
+  XCloseDevice (xdisplay, xdevice);
67f8b7
+}
67f8b7
+
67f8b7
+static void
67f8b7
+change_synaptics_speed (ClutterInputDevice *device,
67f8b7
+                        gdouble             speed)
67f8b7
+{
67f8b7
+  MetaDisplay *display = meta_get_display ();
67f8b7
+  MetaBackend *backend = meta_get_backend ();
67f8b7
+  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
67f8b7
+  XDevice *xdevice;
67f8b7
+  XPtrFeedbackControl feedback;
67f8b7
+  XFeedbackState *states, *state;
67f8b7
+  int i, num_feedbacks, motion_threshold, numerator, denominator;
67f8b7
+  gfloat motion_acceleration;
67f8b7
+
67f8b7
+  xdevice = XOpenDevice(xdisplay, clutter_input_device_get_device_id (device));
67f8b7
+  if (!xdevice)
67f8b7
+    return;
67f8b7
+  /* Get the list of feedbacks for the device */
67f8b7
+  states = XGetFeedbackControl (xdisplay, xdevice, &num_feedbacks);
67f8b7
+  if (!states)
67f8b7
+    return;
67f8b7
+
67f8b7
+  /* Calculate acceleration and threshold */
67f8b7
+  motion_acceleration = (speed + 1) * 5; /* speed is [-1..1], map to [0..10] */
67f8b7
+  motion_threshold = CLAMP (10 - floor (motion_acceleration), 1, 10);
67f8b7
+
67f8b7
+  if (motion_acceleration >= 1.0)
67f8b7
+    {
67f8b7
+      /* we want to get the acceleration, with a resolution of 0.5
67f8b7
+       */
67f8b7
+      if ((motion_acceleration - floor (motion_acceleration)) < 0.25)
67f8b7
+        {
67f8b7
+          numerator = floor (motion_acceleration);
67f8b7
+          denominator = 1;
67f8b7
+        }
67f8b7
+      else if ((motion_acceleration - floor (motion_acceleration)) < 0.5)
67f8b7
+        {
67f8b7
+          numerator = ceil (2.0 * motion_acceleration);
67f8b7
+          denominator = 2;
67f8b7
+        }
67f8b7
+      else if ((motion_acceleration - floor (motion_acceleration)) < 0.75)
67f8b7
+        {
67f8b7
+          numerator = floor (2.0 *motion_acceleration);
67f8b7
+          denominator = 2;
67f8b7
+        }
67f8b7
+      else
67f8b7
+        {
67f8b7
+          numerator = ceil (motion_acceleration);
67f8b7
+          denominator = 1;
67f8b7
+        }
67f8b7
+    }
67f8b7
+  else if (motion_acceleration < 1.0 && motion_acceleration > 0)
67f8b7
+    {
67f8b7
+      /* This we do to 1/10ths */
67f8b7
+      numerator = floor (motion_acceleration * 10) + 1;
67f8b7
+      denominator= 10;
67f8b7
+    }
67f8b7
+  else
67f8b7
+    {
67f8b7
+      numerator = -1;
67f8b7
+      denominator = -1;
67f8b7
+    }
67f8b7
+
67f8b7
+  if (display)
67f8b7
+    meta_error_trap_push (display);
67f8b7
+
67f8b7
+  state = (XFeedbackState *) states;
67f8b7
+
67f8b7
+  for (i = 0; i < num_feedbacks; i++)
67f8b7
+    {
67f8b7
+      if (state->class == PtrFeedbackClass)
67f8b7
+        {
67f8b7
+          /* And tell the device */
67f8b7
+          feedback.class      = PtrFeedbackClass;
67f8b7
+          feedback.length     = sizeof (XPtrFeedbackControl);
67f8b7
+          feedback.id         = state->id;
67f8b7
+          feedback.threshold  = motion_threshold;
67f8b7
+          feedback.accelNum   = numerator;
67f8b7
+          feedback.accelDenom = denominator;
67f8b7
+
67f8b7
+          XChangeFeedbackControl (xdisplay, xdevice,
67f8b7
+                                  DvAccelNum | DvAccelDenom | DvThreshold,
67f8b7
+                                  (XFeedbackControl *) &feedback);
67f8b7
+          break;
67f8b7
+        }
67f8b7
+
67f8b7
+      state = (XFeedbackState *) ((char *) state + state->length);
67f8b7
+    }
67f8b7
+
67f8b7
+  if (display && meta_error_trap_pop_with_return (display))
67f8b7
+    {
67f8b7
+      g_warning ("Could not set synaptics touchpad acceleration for %s",
67f8b7
+                 clutter_input_device_get_device_name (device));
67f8b7
+    }
67f8b7
+
67f8b7
+  XFreeFeedbackList (states);
67f8b7
+  XCloseDevice (xdisplay, xdevice);
67f8b7
+}
67f8b7
+
67f8b7
 static void
67f8b7
 meta_input_settings_x11_set_send_events (MetaInputSettings        *settings,
67f8b7
                                          ClutterInputDevice       *device,
67f8b7
@@ -126,6 +298,13 @@ meta_input_settings_x11_set_send_events (MetaInputSettings        *settings,
67f8b7
   guchar values[2] = { 0 }; /* disabled, disabled-on-external-mouse */
67f8b7
   guchar *available;
67f8b7
 
67f8b7
+  if (is_device_synaptics (device))
67f8b7
+    {
67f8b7
+      values[0] = mode != G_DESKTOP_DEVICE_SEND_EVENTS_ENABLED;
67f8b7
+      change_property (device, "Synaptics Off", XA_INTEGER, 8, &values, 1);
67f8b7
+      return;
67f8b7
+    }
67f8b7
+
67f8b7
   available = get_property (device, "libinput Send Events Modes Available",
67f8b7
                             XA_INTEGER, 8, 2);
67f8b7
   if (!available)
67f8b7
@@ -178,6 +357,12 @@ meta_input_settings_x11_set_speed (MetaInputSettings  *settings,
67f8b7
   Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
67f8b7
   gfloat value = speed;
67f8b7
 
67f8b7
+  if (is_device_synaptics (device))
67f8b7
+    {
67f8b7
+      change_synaptics_speed (device, speed);
67f8b7
+      return;
67f8b7
+    }
67f8b7
+
67f8b7
   change_property (device, "libinput Accel Speed",
67f8b7
                    XInternAtom (xdisplay, "FLOAT", False),
67f8b7
                    32, &value, 1);
67f8b7
@@ -190,6 +375,18 @@ meta_input_settings_x11_set_left_handed (MetaInputSettings  *settings,
67f8b7
 {
67f8b7
   guchar value = (enabled) ? 1 : 0;
67f8b7
 
67f8b7
+  if (is_device_synaptics (device))
67f8b7
+    {
67f8b7
+      GSettings *settings;
67f8b7
+
67f8b7
+      settings = g_settings_new ("org.gnome.desktop.peripherals.touchpad");
67f8b7
+      change_synaptics_tap_left_handed (device,
67f8b7
+                                        g_settings_get_boolean (settings, "tap-to-click"),
67f8b7
+                                        enabled);
67f8b7
+      g_object_unref (settings);
67f8b7
+      return;
67f8b7
+    }
67f8b7
+
67f8b7
   change_property (device, "libinput Left Handed Enabled",
67f8b7
                    XA_INTEGER, 8, &value, 1);
67f8b7
 }
67f8b7
@@ -201,6 +398,20 @@ meta_input_settings_x11_set_tap_enabled (MetaInputSettings  *settings,
67f8b7
 {
67f8b7
   guchar value = (enabled) ? 1 : 0;
67f8b7
 
67f8b7
+  if (is_device_synaptics (device))
67f8b7
+    {
67f8b7
+      GDesktopTouchpadHandedness handedness;
67f8b7
+      GSettings *settings;
67f8b7
+
67f8b7
+      settings = g_settings_new ("org.gnome.desktop.peripherals.touchpad");
67f8b7
+      handedness = g_settings_get_enum (settings, "left-handed");
67f8b7
+      g_object_unref (settings);
67f8b7
+
67f8b7
+      change_synaptics_tap_left_handed (device, enabled,
67f8b7
+                                        handedness == G_DESKTOP_TOUCHPAD_HANDEDNESS_LEFT);
67f8b7
+      return;
67f8b7
+    }
67f8b7
+
67f8b7
   change_property (device, "libinput Tapping Enabled",
67f8b7
                    XA_INTEGER, 8, &value, 1);
67f8b7
 }
67f8b7
@@ -212,6 +423,27 @@ meta_input_settings_x11_set_invert_scroll (MetaInputSettings  *settings,
67f8b7
 {
67f8b7
   guchar value = (inverted) ? 1 : 0;
67f8b7
 
67f8b7
+  if (is_device_synaptics (device))
67f8b7
+    {
67f8b7
+      gint32 *scrolling_distance;
67f8b7
+
67f8b7
+      scrolling_distance = get_property (device, "Synaptics Scrolling Distance",
67f8b7
+                                         XA_INTEGER, 32, 2);
67f8b7
+      if (scrolling_distance)
67f8b7
+        {
67f8b7
+          scrolling_distance[0] = inverted ?
67f8b7
+            -abs (scrolling_distance[0]) : abs (scrolling_distance[0]);
67f8b7
+          scrolling_distance[1] = inverted ?
67f8b7
+            -abs (scrolling_distance[1]) : abs (scrolling_distance[1]);
67f8b7
+
67f8b7
+          change_property (device, "Synaptics Scrolling Distance",
67f8b7
+                           XA_INTEGER, 32, scrolling_distance, 2);
67f8b7
+          meta_XFree (scrolling_distance);
67f8b7
+        }
67f8b7
+
67f8b7
+      return;
67f8b7
+    }
67f8b7
+
67f8b7
   change_property (device, "libinput Natural Scrolling Enabled",
67f8b7
                    XA_INTEGER, 8, &value, 1);
67f8b7
 }
67f8b7
@@ -225,6 +457,22 @@ meta_input_settings_x11_set_edge_scroll (MetaInputSettings            *settings,
67f8b7
   guchar *current = NULL;
67f8b7
   guchar *available = NULL;
67f8b7
 
67f8b7
+  if (is_device_synaptics (device))
67f8b7
+    {
67f8b7
+      current = get_property (device, "Synaptics Edge Scrolling",
67f8b7
+                              XA_INTEGER, 8, 3);
67f8b7
+      if (current)
67f8b7
+        {
67f8b7
+          current[0] = !!edge_scroll_enabled;
67f8b7
+          current[1] = !!edge_scroll_enabled;
67f8b7
+          change_property (device, "Synaptics Edge Scrolling",
67f8b7
+                           XA_INTEGER, 8, current, 3);
67f8b7
+          meta_XFree (current);
67f8b7
+        }
67f8b7
+
67f8b7
+      return;
67f8b7
+    }
67f8b7
+
67f8b7
   available = get_property (device, "libinput Scroll Methods Available",
67f8b7
                             XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS);
67f8b7
   if (!available || !available[SCROLL_METHOD_FIELD_EDGE])
67f8b7
@@ -254,6 +502,22 @@ meta_input_settings_x11_set_two_finger_scroll (MetaInputSettings            *set
67f8b7
   guchar *current = NULL;
67f8b7
   guchar *available = NULL;
67f8b7
 
67f8b7
+  if (is_device_synaptics (device))
67f8b7
+    {
67f8b7
+      current = get_property (device, "Synaptics Two-Finger Scrolling",
67f8b7
+                              XA_INTEGER, 8, 2);
67f8b7
+      if (current)
67f8b7
+        {
67f8b7
+          current[0] = !!two_finger_scroll_enabled;
67f8b7
+          current[1] = !!two_finger_scroll_enabled;
67f8b7
+          change_property (device, "Synaptics Two-Finger Scrolling",
67f8b7
+                           XA_INTEGER, 8, current, 2);
67f8b7
+          meta_XFree (current);
67f8b7
+        }
67f8b7
+
67f8b7
+      return;
67f8b7
+    }
67f8b7
+
67f8b7
   available = get_property (device, "libinput Scroll Methods Available",
67f8b7
                             XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS);
67f8b7
   if (!available || !available[SCROLL_METHOD_FIELD_2FG])
67f8b7
-- 
67f8b7
2.9.3
67f8b7