From 81986e9b3c16efa170b2bb4fe2af05a30b9386b3 Mon Sep 17 00:00:00 2001 From: Rui Matos Date: Mon, 9 Oct 2017 18:37:11 +0200 Subject: [PATCH 1/4] backends/x11: Fix a small memory leak Introduced in "backends/x11: Support synaptics configuration". --- src/backends/x11/meta-input-settings-x11.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c index 467a9b7..27995c8 100644 --- a/src/backends/x11/meta-input-settings-x11.c +++ b/src/backends/x11/meta-input-settings-x11.c @@ -222,6 +222,7 @@ change_synaptics_tap_left_handed (ClutterInputDevice *device, buttons[0] = left_handed ? 3 : 1; buttons[2] = left_handed ? 1 : 3; XSetDeviceButtonMapping (xdisplay, xdevice, buttons, n_buttons); + g_free (buttons); if (display && meta_error_trap_pop_with_return (display)) { -- 1.8.3.1 From c3f4dc97cdb4f1b63e43e38daf02e676d207ad37 Mon Sep 17 00:00:00 2001 From: Rui Matos Date: Mon, 9 Oct 2017 18:39:52 +0200 Subject: [PATCH 2/4] backends/x11: Add a synaptics check for two finger scroll availability Commit "backends/x11: Support synaptics configuration" added support for synaptics two finger scrolling but didn't add the code to check that it is available resulting in the upper layer always assuming it isn't. --- src/backends/x11/meta-input-settings-x11.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c index 27995c8..4c2709c 100644 --- a/src/backends/x11/meta-input-settings-x11.c +++ b/src/backends/x11/meta-input-settings-x11.c @@ -621,6 +621,17 @@ meta_input_settings_x11_has_two_finger_scroll (MetaInputSettings *settings, guchar *available = NULL; gboolean has_two_finger = TRUE; + if (is_device_synaptics (device)) + { + available = get_property (device, "Synaptics Capabilities", + XA_INTEGER, 8, 4); + if (!available || !available[3]) + has_two_finger = FALSE; + + meta_XFree (available); + return has_two_finger; + } + available = get_property (device, "libinput Scroll Methods Available", XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS); if (!available || !available[SCROLL_METHOD_FIELD_2FG]) -- 1.8.3.1 From fd94f5fd842f0f0f9e4a28e69716a30669e2e848 Mon Sep 17 00:00:00 2001 From: Rui Matos Date: Mon, 9 Oct 2017 18:55:56 +0200 Subject: [PATCH 3/4] backends/x11: Add disable while typing support for synaptics This is basically a copy of the old g-s-d mouse plugin code to manage syndaemon when the synaptics driver is being used. --- src/backends/x11/meta-input-settings-x11.c | 112 +++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c index 4c2709c..9a85f94 100644 --- a/src/backends/x11/meta-input-settings-x11.c +++ b/src/backends/x11/meta-input-settings-x11.c @@ -35,6 +35,9 @@ #ifdef HAVE_LIBGUDEV #include #endif +#ifdef __linux +#include +#endif #include #include "backends/meta-logical-monitor.h" @@ -44,6 +47,8 @@ typedef struct _MetaInputSettingsX11Private #ifdef HAVE_LIBGUDEV GUdevClient *udev_client; #endif + gboolean syndaemon_spawned; + GPid syndaemon_pid; } MetaInputSettingsX11Private; G_DEFINE_TYPE_WITH_PRIVATE (MetaInputSettingsX11, meta_input_settings_x11, @@ -328,6 +333,107 @@ change_synaptics_speed (ClutterInputDevice *device, XFreeFeedbackList (states); } +/* Ensure that syndaemon dies together with us, to avoid running several of + * them */ +static void +setup_syndaemon (gpointer user_data) +{ +#ifdef __linux + prctl (PR_SET_PDEATHSIG, SIGHUP); +#endif +} + +static gboolean +have_program_in_path (const char *name) +{ + gchar *path; + gboolean result; + + path = g_find_program_in_path (name); + result = (path != NULL); + g_free (path); + return result; +} + +static void +syndaemon_died (GPid pid, + gint status, + gpointer user_data) +{ + MetaInputSettingsX11 *settings_x11 = META_INPUT_SETTINGS_X11 (user_data); + MetaInputSettingsX11Private *priv = + meta_input_settings_x11_get_instance_private (settings_x11); + GError *error = NULL; + + if (!g_spawn_check_exit_status (status, &error)) + { + if ((WIFSIGNALED (status) && WTERMSIG (status) != SIGHUP) || + error->domain == G_SPAWN_EXIT_ERROR) + g_warning ("Syndaemon exited unexpectedly: %s", error->message); + g_error_free (error); + } + + g_spawn_close_pid (pid); + priv->syndaemon_spawned = FALSE; +} + +static void +set_synaptics_disable_w_typing (MetaInputSettings *settings, + gboolean state) +{ + MetaInputSettingsX11 *settings_x11 = META_INPUT_SETTINGS_X11 (settings); + MetaInputSettingsX11Private *priv = + meta_input_settings_x11_get_instance_private (settings_x11); + + if (state) + { + GError *error = NULL; + GPtrArray *args; + + if (priv->syndaemon_spawned) + return; + + if (!have_program_in_path ("syndaemon")) + return; + + args = g_ptr_array_new (); + + g_ptr_array_add (args, "syndaemon"); + g_ptr_array_add (args, "-i"); + g_ptr_array_add (args, "1.0"); + g_ptr_array_add (args, "-t"); + g_ptr_array_add (args, "-K"); + g_ptr_array_add (args, "-R"); + g_ptr_array_add (args, NULL); + + /* we must use G_SPAWN_DO_NOT_REAP_CHILD to avoid + * double-forking, otherwise syndaemon will immediately get + * killed again through (PR_SET_PDEATHSIG when the intermediate + * process dies */ + g_spawn_async (g_get_home_dir (), (char **) args->pdata, NULL, + G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD, setup_syndaemon, NULL, + &priv->syndaemon_pid, &error); + + priv->syndaemon_spawned = (error == NULL); + g_ptr_array_free (args, TRUE); + + if (error) + { + g_warning ("Failed to launch syndaemon: %s", error->message); + g_error_free (error); + } + else + { + g_child_watch_add (priv->syndaemon_pid, syndaemon_died, settings); + } + } + else if (priv->syndaemon_spawned) + { + kill (priv->syndaemon_pid, SIGHUP); + priv->syndaemon_spawned = FALSE; + } +} + static void meta_input_settings_x11_set_send_events (MetaInputSettings *settings, ClutterInputDevice *device, @@ -452,6 +558,12 @@ meta_input_settings_x11_set_disable_while_typing (MetaInputSettings *settings, { guchar value = (enabled) ? 1 : 0; + if (is_device_synaptics (device)) + { + set_synaptics_disable_w_typing (settings, enabled); + return; + } + change_property (device, "libinput Disable While Typing Enabled", XA_INTEGER, 8, &value, 1); } -- 1.8.3.1 From f5f9195fe23c0af8a498a13ca6bc5521a0c9e6ce Mon Sep 17 00:00:00 2001 From: Rui Matos Date: Tue, 10 Oct 2017 19:07:27 +0200 Subject: [PATCH 4/4] backends/x11: Support plain old X device configuration We re-use part of the code added to support synaptics and add a few bits specific for xorg-x11-drv-evdev devices. --- src/backends/x11/meta-input-settings-x11.c | 96 +++++++++++++++++++++++------- 1 file changed, 74 insertions(+), 22 deletions(-) diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c index 9a85f94..cb4eb00 100644 --- a/src/backends/x11/meta-input-settings-x11.c +++ b/src/backends/x11/meta-input-settings-x11.c @@ -179,35 +179,35 @@ is_device_synaptics (ClutterInputDevice *device) return TRUE; } +static gboolean +is_device_libinput (ClutterInputDevice *device) +{ + guchar *has_setting; + + /* We just need looking for a synaptics-specific property */ + has_setting = get_property (device, "libinput Send Events Modes Available", XA_INTEGER, 8, 2); + if (!has_setting) + return FALSE; + + meta_XFree (has_setting); + return TRUE; +} + static void -change_synaptics_tap_left_handed (ClutterInputDevice *device, - gboolean tap_enabled, - gboolean left_handed) +change_x_device_left_handed (ClutterInputDevice *device, + gboolean left_handed) { MetaDisplay *display = meta_get_display (); MetaBackend *backend = meta_get_backend (); Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); XDevice *xdevice; - guchar *tap_action, *buttons; + guchar *buttons; guint buttons_capacity = 16, n_buttons; xdevice = device_ensure_xdevice (device); if (!xdevice) return; - tap_action = get_property (device, "Synaptics Tap Action", - XA_INTEGER, 8, 7); - if (!tap_action) - return; - - tap_action[4] = tap_enabled ? (left_handed ? 3 : 1) : 0; - tap_action[5] = tap_enabled ? (left_handed ? 1 : 3) : 0; - tap_action[6] = tap_enabled ? 2 : 0; - - change_property (device, "Synaptics Tap Action", - XA_INTEGER, 8, tap_action, 7); - meta_XFree (tap_action); - if (display) meta_error_trap_push (display); buttons = g_new (guchar, buttons_capacity); @@ -231,14 +231,37 @@ change_synaptics_tap_left_handed (ClutterInputDevice *device, if (display && meta_error_trap_pop_with_return (display)) { - g_warning ("Could not set synaptics touchpad left-handed for %s", + g_warning ("Could not set left-handed for %s", clutter_input_device_get_device_name (device)); } } static void -change_synaptics_speed (ClutterInputDevice *device, - gdouble speed) +change_synaptics_tap_left_handed (ClutterInputDevice *device, + gboolean tap_enabled, + gboolean left_handed) +{ + guchar *tap_action; + + tap_action = get_property (device, "Synaptics Tap Action", + XA_INTEGER, 8, 7); + if (!tap_action) + return; + + tap_action[4] = tap_enabled ? (left_handed ? 3 : 1) : 0; + tap_action[5] = tap_enabled ? (left_handed ? 1 : 3) : 0; + tap_action[6] = tap_enabled ? 2 : 0; + + change_property (device, "Synaptics Tap Action", + XA_INTEGER, 8, tap_action, 7); + meta_XFree (tap_action); + + change_x_device_left_handed (device, left_handed); +} + +static void +change_x_device_speed (ClutterInputDevice *device, + gdouble speed) { MetaDisplay *display = meta_get_display (); MetaBackend *backend = meta_get_backend (); @@ -333,6 +356,23 @@ change_synaptics_speed (ClutterInputDevice *device, XFreeFeedbackList (states); } +static void +change_x_device_scroll_button (ClutterInputDevice *device, + guint button) +{ + guchar value; + + value = button > 0 ? 1 : 0; + change_property (device, "Evdev Wheel Emulation", + XA_INTEGER, 8, &value, 1); + if (button > 0) + { + value = button; + change_property (device, "Evdev Wheel Emulation Button", + XA_INTEGER, 8, &value, 1); + } +} + /* Ensure that syndaemon dies together with us, to avoid running several of * them */ static void @@ -501,9 +541,10 @@ meta_input_settings_x11_set_speed (MetaInputSettings *settings, Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); gfloat value = speed; - if (is_device_synaptics (device)) + if (is_device_synaptics (device) || + !is_device_libinput (device)) { - change_synaptics_speed (device, speed); + change_x_device_speed (device, speed); return; } @@ -545,6 +586,11 @@ meta_input_settings_x11_set_left_handed (MetaInputSettings *settings, g_object_unref (settings); return; } + else if (!is_device_libinput (device)) + { + change_x_device_left_handed (device, enabled); + return; + } change_property (device, "libinput Left Handed Enabled", XA_INTEGER, 8, &value, 1); @@ -758,6 +804,12 @@ meta_input_settings_x11_set_scroll_button (MetaInputSettings *settings, ClutterInputDevice *device, guint button) { + if (!is_device_libinput (device)) + { + change_x_device_scroll_button (device, button); + return; + } + change_property (device, "libinput Button Scrolling Button", XA_INTEGER, 32, &button, 1); } -- 1.8.3.1