From ec36d9b9c774597b6793998be5857d1331e3a70f5a5755f2f4420a3957074058 Mon Sep 17 00:00:00 2001 From: Dominique Leuenberger Date: Tue, 8 Mar 2016 15:53:53 +0000 Subject: [PATCH] Accepting request 368184 from GNOME:Next - Add gnome-settings-daemon-revert-libinput-mandatory.patch: do not force libinput driver on SLE. - Re-add "hotplug-command" helper when building for SLE. OBS-URL: https://build.opensuse.org/request/show/368184 OBS-URL: https://build.opensuse.org/package/show/GNOME:Factory/gnome-settings-daemon?expand=0&rev=240 --- ...ngs-daemon-revert-libinput-mandatory.patch | 2015 +++++++++++++++++ gnome-settings-daemon.changes | 7 + gnome-settings-daemon.spec | 10 +- 3 files changed, 2030 insertions(+), 2 deletions(-) create mode 100644 gnome-settings-daemon-revert-libinput-mandatory.patch diff --git a/gnome-settings-daemon-revert-libinput-mandatory.patch b/gnome-settings-daemon-revert-libinput-mandatory.patch new file mode 100644 index 0000000..8d1d65e --- /dev/null +++ b/gnome-settings-daemon-revert-libinput-mandatory.patch @@ -0,0 +1,2015 @@ +From f5aa66f135c9e7e9c57363c8933e6a87d0900112 Mon Sep 17 00:00:00 2001 +From: Frederic Crozat +Date: Fri, 4 Mar 2016 15:47:30 +0100 +Subject: [PATCH 1/3] Revert "mouse: Remove support for non-libinput mouse + configurations" + +This reverts commit 66c211ff24bec6a938d6a6a0dd8730f4689ef383. +--- + plugins/mouse/gsd-mouse-manager.c | 1255 ++++++++++++++++++++++++++++++++++++- + 1 file changed, 1252 insertions(+), 3 deletions(-) + +diff --git a/plugins/mouse/gsd-mouse-manager.c b/plugins/mouse/gsd-mouse-manager.c +index cf2c28c..da7b378 100644 +--- a/plugins/mouse/gsd-mouse-manager.c ++++ b/plugins/mouse/gsd-mouse-manager.c +@@ -19,17 +19,39 @@ + + #include "config.h" + ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef __linux ++#include ++#endif ++ + #include + + #include + #include + #include ++#include ++#include ++#include ++#include ++#include ++#include + + #include + ++#include ++#include ++ + #include "gnome-settings-bus.h" + #include "gnome-settings-profile.h" + #include "gsd-mouse-manager.h" ++#include "gsd-input-helper.h" + #include "gsd-enums.h" + #include "gsd-settings-migrate.h" + +@@ -38,20 +60,42 @@ + #define GSD_SETTINGS_MOUSE_SCHEMA "org.gnome.settings-daemon.peripherals.mouse" + #define GSETTINGS_MOUSE_SCHEMA "org.gnome.desktop.peripherals.mouse" + #define GSETTINGS_TOUCHPAD_SCHEMA "org.gnome.desktop.peripherals.touchpad" ++#define GSETTINGS_TRACKBALL_SCHEMA "org.gnome.desktop.peripherals.trackball" ++ ++/* Keys for both touchpad and mouse */ ++#define KEY_LEFT_HANDED "left-handed" /* a boolean for mouse, an enum for touchpad */ ++#define KEY_SPEED "speed" ++ ++/* Touchpad settings */ ++#define KEY_EDGE_SCROLLING_ENABLED "edge-scrolling-enabled" ++#define KEY_TAP_TO_CLICK "tap-to-click" ++#define KEY_SEND_EVENTS "send-events" ++#define KEY_NATURAL_SCROLL_ENABLED "natural-scroll" + + /* Mouse settings */ + #define KEY_LOCATE_POINTER "locate-pointer" + #define KEY_DWELL_CLICK_ENABLED "dwell-click-enabled" + #define KEY_SECONDARY_CLICK_ENABLED "secondary-click-enabled" + ++/* Trackball settings */ ++#define KEY_SCROLL_WHEEL_BUTTON "scroll-wheel-emulation-button" ++ + struct GsdMouseManagerPrivate + { + guint start_idle_id; + GSettings *touchpad_settings; +- GSettings *mouse_a11y_settings; + GSettings *mouse_settings; ++ GSettings *mouse_a11y_settings; ++ GSettings *trackball_settings; + GSettings *gsd_mouse_settings; ++ GdkDeviceManager *device_manager; ++ guint device_added_id; ++ guint device_removed_id; ++ GHashTable *blacklist; ++ + gboolean mousetweaks_daemon_running; ++ gboolean syndaemon_spawned; ++ GPid syndaemon_pid; + gboolean locate_pointer_spawned; + GPid locate_pointer_pid; + }; +@@ -59,6 +103,12 @@ struct GsdMouseManagerPrivate + static void gsd_mouse_manager_class_init (GsdMouseManagerClass *klass); + static void gsd_mouse_manager_init (GsdMouseManager *mouse_manager); + static void gsd_mouse_manager_finalize (GObject *object); ++static void set_tap_to_click (GdkDevice *device, ++ gboolean state, ++ gboolean left_handed); ++static void ensure_touchpad_active (GsdMouseManager *manager); ++static gboolean get_touchpad_enabled (GsdMouseManager *manager); ++ + + G_DEFINE_TYPE (GsdMouseManager, gsd_mouse_manager, G_TYPE_OBJECT) + +@@ -76,6 +126,775 @@ gsd_mouse_manager_class_init (GsdMouseManagerClass *klass) + g_type_class_add_private (klass, sizeof (GsdMouseManagerPrivate)); + } + ++static XDevice * ++open_gdk_device (GdkDevice *device) ++{ ++ XDevice *xdevice; ++ int id; ++ ++ g_object_get (G_OBJECT (device), "device-id", &id, NULL); ++ ++ gdk_error_trap_push (); ++ ++ xdevice = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), id); ++ ++ if (gdk_error_trap_pop () != 0) ++ return NULL; ++ ++ return xdevice; ++} ++ ++static gboolean ++device_info_is_trackball (XDeviceInfo *device_info) ++{ ++ gboolean retval; ++ ++ retval = (device_info->type == XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XI_TRACKBALL, False)); ++ if (retval == FALSE && ++ device_info->name != NULL) { ++ char *lowercase; ++ ++ lowercase = g_ascii_strdown (device_info->name, -1); ++ retval = strstr (lowercase, "trackball") != NULL; ++ g_free (lowercase); ++ } ++ ++ return retval; ++} ++ ++static gboolean ++device_is_trackball (GdkDevice *device) ++{ ++ XDeviceInfo *device_info; ++ gboolean retval = FALSE; ++ gint n_devices; ++ guint i; ++ int id; ++ ++ g_object_get (G_OBJECT (device), "device-id", &id, NULL); ++ ++ gdk_error_trap_push (); ++ ++ device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices); ++ if (device_info == NULL) ++ return retval; ++ ++ for (i = 0; i < n_devices; i++) { ++ if (device_info[i].id != id) ++ continue; ++ ++ retval = device_info_is_trackball (&device_info[i]); ++ break; ++ } ++ XFreeDeviceList (device_info); ++ ++ if (gdk_error_trap_pop () != 0) ++ return FALSE; ++ ++ return retval; ++} ++ ++static gboolean ++device_is_blacklisted (GsdMouseManager *manager, ++ GdkDevice *device) ++{ ++ int id; ++ g_object_get (G_OBJECT (device), "device-id", &id, NULL); ++ if (g_hash_table_lookup (manager->priv->blacklist, GINT_TO_POINTER (id)) != NULL) { ++ g_debug ("device %s (%d) is blacklisted", gdk_device_get_name (device), id); ++ return TRUE; ++ } ++ return FALSE; ++} ++ ++static gboolean ++device_is_ignored (GsdMouseManager *manager, ++ GdkDevice *device) ++{ ++ GdkInputSource source; ++ const char *name; ++ ++ if (device_is_blacklisted (manager, device)) ++ return TRUE; ++ ++ source = gdk_device_get_source (device); ++ if (source != GDK_SOURCE_MOUSE && ++ source != GDK_SOURCE_TOUCHPAD && ++ source != GDK_SOURCE_CURSOR) ++ return TRUE; ++ ++ name = gdk_device_get_name (device); ++ if (name != NULL && g_str_equal ("Virtual core XTEST pointer", name)) ++ return TRUE; ++ ++ return FALSE; ++} ++ ++static void ++configure_button_layout (guchar *buttons, ++ gint n_buttons, ++ gboolean left_handed) ++{ ++ const gint left_button = 1; ++ gint right_button; ++ gint i; ++ ++ /* if the button is higher than 2 (3rd button) then it's ++ * probably one direction of a scroll wheel or something else ++ * uninteresting ++ */ ++ right_button = MIN (n_buttons, 3); ++ ++ /* If we change things we need to make sure we only swap buttons. ++ * If we end up with multiple physical buttons assigned to the same ++ * logical button the server will complain. This code assumes physical ++ * button 0 is the physical left mouse button, and that the physical ++ * button other than 0 currently assigned left_button or right_button ++ * is the physical right mouse button. ++ */ ++ ++ /* check if the current mapping satisfies the above assumptions */ ++ if (buttons[left_button - 1] != left_button && ++ buttons[left_button - 1] != right_button) ++ /* The current mapping is weird. Swapping buttons is probably not a ++ * good idea. ++ */ ++ return; ++ ++ /* check if we are left_handed and currently not swapped */ ++ if (left_handed && buttons[left_button - 1] == left_button) { ++ /* find the right button */ ++ for (i = 0; i < n_buttons; i++) { ++ if (buttons[i] == right_button) { ++ buttons[i] = left_button; ++ break; ++ } ++ } ++ /* swap the buttons */ ++ buttons[left_button - 1] = right_button; ++ } ++ /* check if we are not left_handed but are swapped */ ++ else if (!left_handed && buttons[left_button - 1] == right_button) { ++ /* find the right button */ ++ for (i = 0; i < n_buttons; i++) { ++ if (buttons[i] == left_button) { ++ buttons[i] = right_button; ++ break; ++ } ++ } ++ /* swap the buttons */ ++ buttons[left_button - 1] = left_button; ++ } ++} ++ ++static gboolean ++xinput_device_has_buttons (GdkDevice *device) ++{ ++ int i; ++ XAnyClassInfo *class_info; ++ ++ /* FIXME can we use the XDevice's classes here instead? */ ++ XDeviceInfo *device_info, *info; ++ gint n_devices; ++ int id; ++ ++ /* Find the XDeviceInfo for the GdkDevice */ ++ g_object_get (G_OBJECT (device), "device-id", &id, NULL); ++ ++ device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices); ++ if (device_info == NULL) ++ return FALSE; ++ ++ info = NULL; ++ for (i = 0; i < n_devices; i++) { ++ if (device_info[i].id == id) { ++ info = &device_info[i]; ++ break; ++ } ++ } ++ if (info == NULL) ++ goto bail; ++ ++ class_info = info->inputclassinfo; ++ for (i = 0; i < info->num_classes; i++) { ++ if (class_info->class == ButtonClass) { ++ XButtonInfo *button_info; ++ ++ button_info = (XButtonInfo *) class_info; ++ if (button_info->num_buttons > 0) { ++ XFreeDeviceList (device_info); ++ return TRUE; ++ } ++ } ++ ++ class_info = (XAnyClassInfo *) (((guchar *) class_info) + ++ class_info->length); ++ } ++ ++bail: ++ XFreeDeviceList (device_info); ++ ++ return FALSE; ++} ++ ++static gboolean ++touchpad_has_single_button (XDevice *device) ++{ ++ Atom type, prop; ++ int format; ++ unsigned long nitems, bytes_after; ++ unsigned char *data; ++ gboolean is_single_button = FALSE; ++ int rc; ++ ++ prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Capabilities", False); ++ if (!prop) ++ return FALSE; ++ ++ gdk_error_trap_push (); ++ rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device, prop, 0, 1, False, ++ XA_INTEGER, &type, &format, &nitems, ++ &bytes_after, &data); ++ if (rc == Success && type == XA_INTEGER && format == 8 && nitems >= 3) ++ is_single_button = (data[0] == 1 && data[1] == 0 && data[2] == 0); ++ ++ if (rc == Success) ++ XFree (data); ++ ++ gdk_error_trap_pop_ignored (); ++ ++ return is_single_button; ++} ++ ++static void ++set_left_handed (GsdMouseManager *manager, ++ GdkDevice *device, ++ gboolean mouse_left_handed, ++ gboolean touchpad_left_handed) ++{ ++ XDevice *xdevice; ++ guchar *buttons; ++ gsize buttons_capacity = 16; ++ gboolean left_handed; ++ gint n_buttons; ++ ++ if (!xinput_device_has_buttons (device)) ++ return; ++ ++ if (xdevice_is_libinput (gdk_x11_device_get_id (device))) ++ return; ++ ++ xdevice = open_gdk_device (device); ++ if (xdevice == NULL) ++ return; ++ ++ g_debug ("setting handedness on %s", gdk_device_get_name (device)); ++ ++ buttons = g_new (guchar, buttons_capacity); ++ ++ /* If the device is a touchpad, swap tap buttons ++ * around too, otherwise a tap would be a right-click */ ++ if (xdevice_is_synaptics (xdevice)) { ++ gboolean tap = g_settings_get_boolean (manager->priv->touchpad_settings, KEY_TAP_TO_CLICK); ++ gboolean single_button = touchpad_has_single_button (xdevice); ++ ++ left_handed = touchpad_left_handed; ++ ++ if (tap && !single_button) ++ set_tap_to_click (device, tap, left_handed); ++ ++ if (single_button) ++ goto out; ++ } else { ++ left_handed = mouse_left_handed; ++ } ++ ++ gdk_error_trap_push (); ++ ++ n_buttons = XGetDeviceButtonMapping (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, ++ buttons, ++ buttons_capacity); ++ ++ while (n_buttons > buttons_capacity) { ++ buttons_capacity = n_buttons; ++ buttons = (guchar *) g_realloc (buttons, ++ buttons_capacity * sizeof (guchar)); ++ ++ n_buttons = XGetDeviceButtonMapping (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, ++ buttons, ++ buttons_capacity); ++ } ++ ++ configure_button_layout (buttons, n_buttons, left_handed); ++ ++ XSetDeviceButtonMapping (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, buttons, n_buttons); ++ gdk_error_trap_pop_ignored (); ++ ++out: ++ xdevice_close (xdevice); ++ g_free (buttons); ++} ++ ++static void ++set_motion (GsdMouseManager *manager, ++ GdkDevice *device) ++{ ++ XDevice *xdevice; ++ XPtrFeedbackControl feedback; ++ XFeedbackState *states, *state; ++ int num_feedbacks; ++ int numerator, denominator; ++ gfloat motion_acceleration; ++ int motion_threshold; ++ GSettings *settings; ++ gdouble speed; ++ guint i; ++ ++ if (xdevice_is_libinput (gdk_x11_device_get_id (device))) ++ return; ++ ++ xdevice = open_gdk_device (device); ++ if (xdevice == NULL) ++ return; ++ ++ g_debug ("setting motion on %s", gdk_device_get_name (device)); ++ ++ if (xdevice_is_synaptics (xdevice)) ++ settings = manager->priv->touchpad_settings; ++ else ++ settings = manager->priv->mouse_settings; ++ ++ speed = g_settings_get_double (settings, KEY_SPEED); ++ ++ /* Calculate acceleration and threshold */ ++ motion_acceleration = (speed + 1) * 5; /* speed is [-1..1], map to [0..10] */ ++ motion_threshold = CLAMP (10 - floor (motion_acceleration), 1, 10); ++ ++ if (motion_acceleration >= 1.0) { ++ /* we want to get the acceleration, with a resolution of 0.5 ++ */ ++ if ((motion_acceleration - floor (motion_acceleration)) < 0.25) { ++ numerator = floor (motion_acceleration); ++ denominator = 1; ++ } else if ((motion_acceleration - floor (motion_acceleration)) < 0.5) { ++ numerator = ceil (2.0 * motion_acceleration); ++ denominator = 2; ++ } else if ((motion_acceleration - floor (motion_acceleration)) < 0.75) { ++ numerator = floor (2.0 *motion_acceleration); ++ denominator = 2; ++ } else { ++ numerator = ceil (motion_acceleration); ++ denominator = 1; ++ } ++ } else if (motion_acceleration < 1.0 && motion_acceleration > 0) { ++ /* This we do to 1/10ths */ ++ numerator = floor (motion_acceleration * 10) + 1; ++ denominator= 10; ++ } else { ++ numerator = -1; ++ denominator = -1; ++ } ++ ++ gdk_error_trap_push (); ++ ++ /* Get the list of feedbacks for the device */ ++ states = XGetFeedbackControl (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, &num_feedbacks); ++ if (states == NULL) ++ goto out; ++ state = (XFeedbackState *) states; ++ for (i = 0; i < num_feedbacks; i++) { ++ if (state->class == PtrFeedbackClass) { ++ /* And tell the device */ ++ feedback.class = PtrFeedbackClass; ++ feedback.length = sizeof (XPtrFeedbackControl); ++ feedback.id = state->id; ++ feedback.threshold = motion_threshold; ++ feedback.accelNum = numerator; ++ feedback.accelDenom = denominator; ++ ++ g_debug ("Setting accel %d/%d, threshold %d for device '%s'", ++ numerator, denominator, motion_threshold, gdk_device_get_name (device)); ++ ++ XChangeFeedbackControl (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), ++ xdevice, ++ DvAccelNum | DvAccelDenom | DvThreshold, ++ (XFeedbackControl *) &feedback); ++ ++ break; ++ } ++ state = (XFeedbackState *) ((char *) state + state->length); ++ } ++ ++ if (gdk_error_trap_pop ()) ++ g_warning ("Error setting acceleration on \"%s\"", gdk_device_get_name (device)); ++ ++ XFreeFeedbackList (states); ++ ++ out: ++ ++ xdevice_close (xdevice); ++} ++ ++/* 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) ++{ ++ GsdMouseManager *manager = GSD_MOUSE_MANAGER (user_data); ++ ++ g_debug ("syndaemon stopped with status %i", status); ++ g_spawn_close_pid (pid); ++ manager->priv->syndaemon_spawned = FALSE; ++} ++ ++static int ++set_disable_w_typing (GsdMouseManager *manager, gboolean state) ++{ ++ if (state && synaptics_is_present ()) { ++ GError *error = NULL; ++ GPtrArray *args; ++ ++ if (manager->priv->syndaemon_spawned) ++ return 0; ++ ++ if (!have_program_in_path ("syndaemon")) ++ return 0; ++ ++ 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, ++ &manager->priv->syndaemon_pid, &error); ++ ++ manager->priv->syndaemon_spawned = (error == NULL); ++ g_ptr_array_free (args, FALSE); ++ ++ if (error) { ++ g_warning ("Failed to launch syndaemon: %s", error->message); ++ g_error_free (error); ++ } else { ++ g_child_watch_add (manager->priv->syndaemon_pid, syndaemon_died, manager); ++ g_debug ("Launched syndaemon"); ++ } ++ } else if (manager->priv->syndaemon_spawned) { ++ kill (manager->priv->syndaemon_pid, SIGHUP); ++ g_spawn_close_pid (manager->priv->syndaemon_pid); ++ manager->priv->syndaemon_spawned = FALSE; ++ g_debug ("Killed syndaemon"); ++ } ++ ++ return 0; ++} ++ ++static void ++set_tap_to_click (GdkDevice *device, ++ gboolean state, ++ gboolean left_handed) ++{ ++ int format, rc; ++ unsigned long nitems, bytes_after; ++ XDevice *xdevice; ++ unsigned char* data; ++ Atom prop_capabilities, prop, type; ++ ++ if (xdevice_is_libinput (gdk_x11_device_get_id (device))) ++ return; ++ ++ prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Tap Action", False); ++ prop_capabilities = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Capabilities", False); ++ if (!prop || !prop_capabilities) ++ return; ++ ++ xdevice = open_gdk_device (device); ++ if (xdevice == NULL) ++ return; ++ ++ if (!xdevice_is_synaptics (xdevice)) { ++ xdevice_close (xdevice); ++ return; ++ } ++ ++ g_debug ("setting tap to click on %s", gdk_device_get_name (device)); ++ ++ gdk_error_trap_push (); ++ rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop_capabilities, 0, 1, ++ False, XA_INTEGER, &type, &format, &nitems, &bytes_after, &data); ++ if (rc == Success && type == XA_INTEGER && format == 8 && nitems >= 1) { ++ if (!(data[0])) { ++ g_debug ("No hardware buttons, enabling tap to click on %s", gdk_device_get_name (device)); ++ state = TRUE; ++ } ++ ++ XFree (data); ++ } ++ ++ rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop, 0, 2, ++ False, XA_INTEGER, &type, &format, &nitems, ++ &bytes_after, &data); ++ ++ if (rc == Success && type == XA_INTEGER && format == 8 && nitems >= 7) { ++ /* Set RLM mapping for 1/2/3 fingers*/ ++ data[4] = (state) ? ((left_handed) ? 3 : 1) : 0; ++ data[5] = (state) ? ((left_handed) ? 1 : 3) : 0; ++ data[6] = (state) ? 2 : 0; ++ XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop, XA_INTEGER, 8, ++ PropModeReplace, data, nitems); ++ } ++ ++ if (rc == Success) ++ XFree (data); ++ ++ if (gdk_error_trap_pop ()) ++ g_warning ("Error in setting tap to click on \"%s\"", gdk_device_get_name (device)); ++ ++ xdevice_close (xdevice); ++} ++ ++static void ++set_horiz_scroll (GdkDevice *device, ++ gboolean state) ++{ ++ int rc; ++ XDevice *xdevice; ++ Atom act_type, prop_edge, prop_twofinger; ++ int act_format; ++ unsigned long nitems, bytes_after; ++ unsigned char *data; ++ ++ if (xdevice_is_libinput (gdk_x11_device_get_id (device))) ++ return; ++ ++ prop_edge = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Edge Scrolling", False); ++ prop_twofinger = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Two-Finger Scrolling", False); ++ ++ if (!prop_edge || !prop_twofinger) ++ return; ++ ++ xdevice = open_gdk_device (device); ++ if (xdevice == NULL) ++ return; ++ ++ if (!xdevice_is_synaptics (xdevice)) { ++ xdevice_close (xdevice); ++ return; ++ } ++ ++ g_debug ("setting horiz scroll on %s", gdk_device_get_name (device)); ++ ++ gdk_error_trap_push (); ++ rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, ++ prop_edge, 0, 1, False, ++ XA_INTEGER, &act_type, &act_format, &nitems, ++ &bytes_after, &data); ++ if (rc == Success && act_type == XA_INTEGER && ++ act_format == 8 && nitems >= 2) { ++ data[1] = (state && data[0]); ++ XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, ++ prop_edge, XA_INTEGER, 8, ++ PropModeReplace, data, nitems); ++ } ++ ++ XFree (data); ++ ++ rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, ++ prop_twofinger, 0, 1, False, ++ XA_INTEGER, &act_type, &act_format, &nitems, ++ &bytes_after, &data); ++ if (rc == Success && act_type == XA_INTEGER && ++ act_format == 8 && nitems >= 2) { ++ data[1] = (state && data[0]); ++ XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, ++ prop_twofinger, XA_INTEGER, 8, ++ PropModeReplace, data, nitems); ++ } ++ ++ if (gdk_error_trap_pop ()) ++ g_warning ("Error in setting horiz scroll on \"%s\"", gdk_device_get_name (device)); ++ ++ if (rc == Success) ++ XFree (data); ++ ++ xdevice_close (xdevice); ++ ++} ++ ++static void ++set_edge_scrolling_enabled (GsdMouseManager *manager, ++ GdkDevice *device, ++ gboolean enabled) ++{ ++ int rc; ++ XDevice *xdevice; ++ Atom act_type, prop, prop_edge, prop_twofinger; ++ int act_format; ++ unsigned long nitems, bytes_after; ++ unsigned char *data; ++ GsdTouchpadScrollMethod method; ++ ++ if (xdevice_is_libinput (gdk_x11_device_get_id (device))) ++ return; ++ ++ prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Capabilities", True); ++ prop_edge = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Edge Scrolling", False); ++ prop_twofinger = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Two-Finger Scrolling", False); ++ ++ if (!prop_edge || !prop_twofinger || !prop) ++ return; ++ ++ xdevice = open_gdk_device (device); ++ if (xdevice == NULL) ++ return; ++ ++ if (!xdevice_is_synaptics (xdevice)) { ++ xdevice_close (xdevice); ++ return; ++ } ++ ++ g_debug ("setting edge scroll on %s", gdk_device_get_name (device)); ++ ++ gdk_error_trap_push (); ++ rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, ++ prop, 0, 2, False, ++ XA_INTEGER, &act_type, &act_format, &nitems, ++ &bytes_after, &data); ++ if (rc == Success && act_type != None) { ++ /* Two-finger scrolling is supported, so enable it */ ++ if (data[3]) ++ method = GSD_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING; ++ ++ XFree (data); ++ } ++ ++ if (enabled && method != GSD_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING) ++ method = GSD_TOUCHPAD_SCROLL_METHOD_EDGE_SCROLLING; ++ else ++ method = GSD_TOUCHPAD_SCROLL_METHOD_DISABLED; ++ ++ rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, ++ prop_edge, 0, 1, False, ++ XA_INTEGER, &act_type, &act_format, &nitems, ++ &bytes_after, &data); ++ if (rc == Success && act_type == XA_INTEGER && ++ act_format == 8 && nitems >= 2) { ++ data[0] = (method == GSD_TOUCHPAD_SCROLL_METHOD_EDGE_SCROLLING) ? 1 : 0; ++ XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, ++ prop_edge, XA_INTEGER, 8, ++ PropModeReplace, data, nitems); ++ } ++ ++ XFree (data); ++ ++ rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, ++ prop_twofinger, 0, 1, False, ++ XA_INTEGER, &act_type, &act_format, &nitems, ++ &bytes_after, &data); ++ if (rc == Success && act_type == XA_INTEGER && ++ act_format == 8 && nitems >= 2) { ++ data[0] = (method == GSD_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING) ? 1 : 0; ++ XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, ++ prop_twofinger, XA_INTEGER, 8, ++ PropModeReplace, data, nitems); ++ } ++ ++ if (gdk_error_trap_pop ()) ++ g_warning ("Error in setting edge scroll on \"%s\"", gdk_device_get_name (device)); ++ ++ if (rc == Success) ++ XFree (data); ++ ++ xdevice_close (xdevice); ++} ++ ++static void ++set_touchpad_disabled (GdkDevice *device) ++{ ++ int id; ++ XDevice *xdevice; ++ ++ if (xdevice_is_libinput (gdk_x11_device_get_id (device))) ++ return; ++ ++ g_object_get (G_OBJECT (device), "device-id", &id, NULL); ++ ++ g_debug ("Trying to set device disabled for \"%s\" (%d)", gdk_device_get_name (device), id); ++ ++ xdevice = open_gdk_device (device); ++ if (xdevice == NULL) ++ return; ++ ++ if (!xdevice_is_synaptics (xdevice)) { ++ xdevice_close (xdevice); ++ return; ++ } ++ ++ if (set_synaptics_device_enabled (id, FALSE) == FALSE) ++ g_warning ("Error disabling device \"%s\" (%d)", gdk_device_get_name (device), id); ++ else ++ g_debug ("Disabled device \"%s\" (%d)", gdk_device_get_name (device), id); ++ ++ xdevice_close (xdevice); ++} ++ ++static void ++set_touchpad_enabled (int id) ++{ ++ XDevice *xdevice; ++ ++ if (xdevice_is_libinput (id)) ++ return; ++ ++ g_debug ("Trying to set device enabled for %d", id); ++ ++ gdk_error_trap_push (); ++ xdevice = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), id); ++ if (gdk_error_trap_pop () != 0) ++ return; ++ ++ if (!xdevice_is_synaptics (xdevice)) { ++ xdevice_close (xdevice); ++ return; ++ } ++ ++ if (set_synaptics_device_enabled (id, TRUE) == FALSE) ++ g_warning ("Error enabling device \"%d\"", id); ++ else ++ g_debug ("Enabled device %d", id); ++ ++ xdevice_close (xdevice); ++} ++ + static void + set_locate_pointer (GsdMouseManager *manager, + gboolean state) +@@ -143,32 +962,418 @@ set_mousetweaks_daemon (GsdMouseManager *manager, + g_free (comm); + } + ++static gboolean ++get_touchpad_handedness (GsdMouseManager *manager, gboolean mouse_left_handed) ++{ ++ switch (g_settings_get_enum (manager->priv->touchpad_settings, KEY_LEFT_HANDED)) { ++ case GSD_TOUCHPAD_HANDEDNESS_RIGHT: ++ return FALSE; ++ case GSD_TOUCHPAD_HANDEDNESS_LEFT: ++ return TRUE; ++ case GSD_TOUCHPAD_HANDEDNESS_MOUSE: ++ return mouse_left_handed; ++ default: ++ g_assert_not_reached (); ++ } ++} ++ ++static void ++set_natural_scroll (GsdMouseManager *manager, ++ GdkDevice *device, ++ gboolean natural_scroll) ++{ ++ XDevice *xdevice; ++ Atom scrolling_distance, act_type; ++ int rc, act_format; ++ unsigned long nitems, bytes_after; ++ unsigned char *data; ++ glong *ptr; ++ ++ xdevice = open_gdk_device (device); ++ if (xdevice == NULL) ++ return; ++ ++ if (!xdevice_is_synaptics (xdevice)) { ++ xdevice_close (xdevice); ++ return; ++ } ++ ++ if (xdevice_is_libinput (gdk_x11_device_get_id (device))) ++ return; ++ ++ g_debug ("Trying to set %s for \"%s\"", ++ natural_scroll ? "natural (reverse) scroll" : "normal scroll", ++ gdk_device_get_name (device)); ++ ++ scrolling_distance = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), ++ "Synaptics Scrolling Distance", False); ++ ++ gdk_error_trap_push (); ++ rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, ++ scrolling_distance, 0, 2, False, ++ XA_INTEGER, &act_type, &act_format, &nitems, ++ &bytes_after, &data); ++ ++ if (rc == Success && act_type == XA_INTEGER && act_format == 32 && nitems >= 2) { ++ ptr = (glong *) data; ++ ++ if (natural_scroll) { ++ ptr[0] = -abs(ptr[0]); ++ ptr[1] = -abs(ptr[1]); ++ } else { ++ ptr[0] = abs(ptr[0]); ++ ptr[1] = abs(ptr[1]); ++ } ++ ++ XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, ++ scrolling_distance, XA_INTEGER, act_format, ++ PropModeReplace, data, nitems); ++ } ++ ++ if (gdk_error_trap_pop ()) ++ g_warning ("Error setting %s for \"%s\"", ++ natural_scroll ? "natural (reverse) scroll" : "normal scroll", ++ gdk_device_get_name (device)); ++ ++ if (rc == Success) ++ XFree (data); ++ ++ xdevice_close (xdevice); ++} ++ ++static void ++set_scroll_wheel_button (GsdMouseManager *manager, ++ GdkDevice *device) ++{ ++ Atom wheel_prop, button_prop; ++ XDevice *xdevice; ++ Atom type; ++ int format; ++ unsigned long nitems, bytes_after; ++ unsigned char *data = NULL; ++ int button; ++ int rc; ++ ++ if (!device_is_trackball (device)) ++ return; ++ ++ if (xdevice_is_libinput (gdk_x11_device_get_id (device))) ++ return; ++ ++ xdevice = open_gdk_device (device); ++ if (xdevice == NULL) ++ return; ++ ++ wheel_prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), ++ "Evdev Wheel Emulation", True); ++ button_prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), ++ "Evdev Wheel Emulation Button", True); ++ ++ if (!wheel_prop || !button_prop) { ++ xdevice_close (xdevice); ++ return; ++ } ++ ++ g_debug ("setting scroll wheel emulation on %s", gdk_device_get_name (device)); ++ ++ gdk_error_trap_push (); ++ ++ button = g_settings_get_int (manager->priv->trackball_settings, KEY_SCROLL_WHEEL_BUTTON); ++ ++ /* Whether scroll wheel emulation is enabled */ ++ rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), ++ xdevice, wheel_prop, 0, 1, False, XA_INTEGER, &type, &format, ++ &nitems, &bytes_after, &data); ++ ++ if (rc == Success && format == 8 && type == XA_INTEGER && nitems == 1) { ++ data[0] = button > 0 ? 1 : 0; ++ ++ XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), ++ xdevice, wheel_prop, type, format, PropModeReplace, data, nitems); ++ } ++ ++ if (data) { ++ XFree (data); ++ data = NULL; ++ } ++ ++ /* Which button is used for the emulation */ ++ if (button > 0) { ++ rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), ++ xdevice, button_prop, 0, 1, False, XA_INTEGER, &type, &format, ++ &nitems, &bytes_after, &data); ++ ++ if (rc == Success && format == 8 && type == XA_INTEGER && nitems == 1) { ++ data[0] = button; ++ ++ XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), ++ xdevice, button_prop, type, format, PropModeReplace, data, nitems); ++ } ++ ++ if (data) ++ XFree (data); ++ } ++ ++ if (gdk_error_trap_pop ()) ++ g_warning ("Error in setting scroll wheel emulation on \"%s\"", gdk_device_get_name (device)); ++ ++ xdevice_close (xdevice); ++} ++ ++static gboolean ++get_touchpad_enabled (GsdMouseManager *manager) ++{ ++ GDesktopDeviceSendEvents send_events; ++ ++ send_events = g_settings_get_enum (manager->priv->touchpad_settings, KEY_SEND_EVENTS); ++ ++ if (send_events == G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE) { ++ /* FIXME: mouse_is_present() also finds internal ones... */ ++ return (!mouse_is_present () && !trackball_is_present ()); ++ ++ } ++ ++ return send_events == G_DESKTOP_DEVICE_SEND_EVENTS_ENABLED ? TRUE : FALSE; ++} ++ ++static void ++set_mouse_settings (GsdMouseManager *manager, ++ GdkDevice *device) ++{ ++ gboolean mouse_left_handed, touchpad_left_handed; ++ ++ if (xdevice_is_libinput (gdk_x11_device_get_id (device))) ++ return; ++ ++ mouse_left_handed = g_settings_get_boolean (manager->priv->mouse_settings, KEY_LEFT_HANDED); ++ touchpad_left_handed = get_touchpad_handedness (manager, mouse_left_handed); ++ set_left_handed (manager, device, mouse_left_handed, touchpad_left_handed); ++ ++ set_motion (manager, device); ++ ++ set_tap_to_click (device, g_settings_get_boolean (manager->priv->touchpad_settings, KEY_TAP_TO_CLICK), touchpad_left_handed); ++ set_edge_scrolling_enabled (manager, device, g_settings_get_boolean (manager->priv->touchpad_settings, KEY_EDGE_SCROLLING_ENABLED)); ++ set_horiz_scroll (device, TRUE); ++ set_natural_scroll (manager, device, g_settings_get_boolean (manager->priv->touchpad_settings, KEY_NATURAL_SCROLL_ENABLED)); ++ ++ set_scroll_wheel_button (manager, device); ++} ++ + static void + mouse_callback (GSettings *settings, + const gchar *key, + GsdMouseManager *manager) + { ++ GList *devices, *l; ++ + if (g_str_equal (key, KEY_DWELL_CLICK_ENABLED) || + g_str_equal (key, KEY_SECONDARY_CLICK_ENABLED)) { + set_mousetweaks_daemon (manager, + g_settings_get_boolean (settings, KEY_DWELL_CLICK_ENABLED), + g_settings_get_boolean (settings, KEY_SECONDARY_CLICK_ENABLED)); ++ return; + } else if (g_str_equal (key, KEY_LOCATE_POINTER)) { + set_locate_pointer (manager, g_settings_get_boolean (settings, KEY_LOCATE_POINTER)); ++ return; + } ++ ++ devices = gdk_device_manager_list_devices (manager->priv->device_manager, GDK_DEVICE_TYPE_SLAVE); ++ ++ for (l = devices; l != NULL; l = l->next) { ++ GdkDevice *device = l->data; ++ ++ if (device_is_ignored (manager, device)) ++ continue; ++ ++ if (xdevice_is_libinput (gdk_x11_device_get_id (device))) ++ continue; ++ ++ if (g_str_equal (key, KEY_LEFT_HANDED)) { ++ gboolean mouse_left_handed; ++ mouse_left_handed = g_settings_get_boolean (settings, KEY_LEFT_HANDED); ++ set_left_handed (manager, device, mouse_left_handed, get_touchpad_handedness (manager, mouse_left_handed)); ++ } else if (g_str_equal (key, KEY_SPEED)) { ++ set_motion (manager, device); ++ } ++ } ++ g_list_free (devices); ++} ++ ++static void ++touchpad_callback (GSettings *settings, ++ const gchar *key, ++ GsdMouseManager *manager) ++{ ++ GList *devices, *l; ++ ++ devices = gdk_device_manager_list_devices (manager->priv->device_manager, GDK_DEVICE_TYPE_SLAVE); ++ ++ for (l = devices; l != NULL; l = l->next) { ++ GdkDevice *device = l->data; ++ ++ if (device_is_ignored (manager, device)) ++ continue; ++ ++ if (xdevice_is_libinput (gdk_x11_device_get_id (device))) ++ continue; ++ ++ if (g_str_equal (key, KEY_TAP_TO_CLICK)) { ++ gboolean mouse_left_handed; ++ mouse_left_handed = g_settings_get_boolean (manager->priv->mouse_settings, KEY_LEFT_HANDED); ++ set_tap_to_click (device, g_settings_get_boolean (settings, key), ++ get_touchpad_handedness (manager, mouse_left_handed)); ++ } else if (g_str_equal (key, KEY_EDGE_SCROLLING_ENABLED)) { ++ set_edge_scrolling_enabled (manager, device, g_settings_get_boolean (settings, key)); ++ set_horiz_scroll (device, TRUE); ++ } else if (g_str_equal (key, KEY_SPEED)) { ++ set_motion (manager, device); ++ } else if (g_str_equal (key, KEY_LEFT_HANDED)) { ++ gboolean mouse_left_handed; ++ mouse_left_handed = g_settings_get_boolean (manager->priv->mouse_settings, KEY_LEFT_HANDED); ++ set_left_handed (manager, device, mouse_left_handed, get_touchpad_handedness (manager, mouse_left_handed)); ++ } else if (g_str_equal (key, KEY_NATURAL_SCROLL_ENABLED)) { ++ set_natural_scroll (manager, device, g_settings_get_boolean (settings, key)); ++ } ++ } ++ g_list_free (devices); ++ ++ if (g_str_equal (key, KEY_SEND_EVENTS)) { ++ ensure_touchpad_active (manager); ++ } ++} ++ ++static void ++trackball_callback (GSettings *settings, ++ const gchar *key, ++ GsdMouseManager *manager) ++{ ++ GList *devices, *l; ++ ++ devices = gdk_device_manager_list_devices (manager->priv->device_manager, GDK_DEVICE_TYPE_SLAVE); ++ ++ for (l = devices; l != NULL; l = l->next) { ++ GdkDevice *device = l->data; ++ ++ if (device_is_ignored (manager, device)) ++ continue; ++ ++ if (xdevice_is_libinput (gdk_x11_device_get_id (device))) ++ return; ++ ++ set_scroll_wheel_button (manager, device); ++ } ++ g_list_free (devices); ++} ++ ++/* Re-enable touchpad when any other pointing device isn't present. */ ++static void ++ensure_touchpad_active (GsdMouseManager *manager) ++{ ++ GList *devices, *l; ++ gboolean state; ++ ++ state = get_touchpad_enabled (manager); ++ if (state) { ++ devices = get_disabled_synaptics (); ++ for (l = devices; l != NULL; l = l->next) { ++ int device_id; ++ ++ device_id = GPOINTER_TO_INT (l->data); ++ set_touchpad_enabled (device_id); ++ } ++ g_list_free (devices); ++ } else { ++ devices = gdk_device_manager_list_devices (manager->priv->device_manager, ++ GDK_DEVICE_TYPE_SLAVE); ++ ++ for (l = devices; l != NULL; l = l->next) { ++ GdkDevice *device = l->data; ++ ++ if (device_is_ignored (manager, device)) ++ continue; ++ if (xdevice_is_libinput (gdk_x11_device_get_id (device))) ++ continue; ++ if (gdk_device_get_source (device) != GDK_SOURCE_TOUCHPAD) ++ continue; ++ ++ set_touchpad_disabled (device); ++ } ++ ++ g_list_free (devices); ++ } ++ ++ set_disable_w_typing (manager, state); ++} ++ ++static void ++device_added_cb (GdkDeviceManager *device_manager, ++ GdkDevice *device, ++ GsdMouseManager *manager) ++{ ++ if (device_is_ignored (manager, device) == FALSE) { ++ if (run_custom_command (device, COMMAND_DEVICE_ADDED) == FALSE) { ++ set_mouse_settings (manager, device); ++ } else { ++ int id; ++ g_object_get (G_OBJECT (device), "device-id", &id, NULL); ++ g_hash_table_insert (manager->priv->blacklist, ++ GINT_TO_POINTER (id), GINT_TO_POINTER (1)); ++ } ++ ++ ensure_touchpad_active (manager); ++ } ++} ++ ++static void ++device_removed_cb (GdkDeviceManager *device_manager, ++ GdkDevice *device, ++ GsdMouseManager *manager) ++{ ++ int id; ++ ++ /* Remove the device from the hash table so that ++ * device_is_ignored () doesn't check for blacklisted devices */ ++ g_object_get (G_OBJECT (device), "device-id", &id, NULL); ++ g_hash_table_remove (manager->priv->blacklist, ++ GINT_TO_POINTER (id)); ++ ++ if (device_is_ignored (manager, device) == FALSE) { ++ run_custom_command (device, COMMAND_DEVICE_REMOVED); ++ ++ ensure_touchpad_active (manager); ++ } ++} ++ ++static void ++set_devicepresence_handler (GsdMouseManager *manager) ++{ ++ GdkDeviceManager *device_manager; ++ ++ device_manager = gdk_display_get_device_manager (gdk_display_get_default ()); ++ ++ manager->priv->device_added_id = g_signal_connect (G_OBJECT (device_manager), "device-added", ++ G_CALLBACK (device_added_cb), manager); ++ manager->priv->device_removed_id = g_signal_connect (G_OBJECT (device_manager), "device-removed", ++ G_CALLBACK (device_removed_cb), manager); ++ manager->priv->device_manager = device_manager; + } + + static void + gsd_mouse_manager_init (GsdMouseManager *manager) + { + manager->priv = GSD_MOUSE_MANAGER_GET_PRIVATE (manager); ++ manager->priv->blacklist = g_hash_table_new (g_direct_hash, g_direct_equal); + } + + static gboolean + gsd_mouse_manager_idle_cb (GsdMouseManager *manager) + { ++ GList *devices, *l; ++ + gnome_settings_profile_start (NULL); + ++ set_devicepresence_handler (manager); ++ + manager->priv->gsd_mouse_settings = g_settings_new (GSD_SETTINGS_MOUSE_SCHEMA); + g_signal_connect (manager->priv->gsd_mouse_settings, "changed", + G_CALLBACK (mouse_callback), manager); +@@ -176,17 +1381,46 @@ gsd_mouse_manager_idle_cb (GsdMouseManager *manager) + manager->priv->mouse_a11y_settings = g_settings_new ("org.gnome.desktop.a11y.mouse"); + g_signal_connect (manager->priv->mouse_a11y_settings, "changed", + G_CALLBACK (mouse_callback), manager); +-#if 0 ++ + manager->priv->mouse_settings = g_settings_new (GSETTINGS_MOUSE_SCHEMA); + g_signal_connect (manager->priv->mouse_settings, "changed", + G_CALLBACK (mouse_callback), manager); +-#endif ++ ++ manager->priv->touchpad_settings = g_settings_new (GSETTINGS_TOUCHPAD_SCHEMA); ++ g_signal_connect (manager->priv->touchpad_settings, "changed", ++ G_CALLBACK (touchpad_callback), manager); ++ ++ manager->priv->trackball_settings = g_settings_new (GSETTINGS_TRACKBALL_SCHEMA); ++ g_signal_connect (manager->priv->trackball_settings, "changed", ++ G_CALLBACK (trackball_callback), manager); ++ ++ manager->priv->syndaemon_spawned = FALSE; + + set_locate_pointer (manager, g_settings_get_boolean (manager->priv->gsd_mouse_settings, KEY_LOCATE_POINTER)); + set_mousetweaks_daemon (manager, + g_settings_get_boolean (manager->priv->mouse_a11y_settings, KEY_DWELL_CLICK_ENABLED), + g_settings_get_boolean (manager->priv->mouse_a11y_settings, KEY_SECONDARY_CLICK_ENABLED)); + ++ devices = gdk_device_manager_list_devices (manager->priv->device_manager, GDK_DEVICE_TYPE_SLAVE); ++ for (l = devices; l != NULL; l = l->next) { ++ GdkDevice *device = l->data; ++ ++ if (device_is_ignored (manager, device)) ++ continue; ++ ++ if (run_custom_command (device, COMMAND_DEVICE_PRESENT) == FALSE) { ++ set_mouse_settings (manager, device); ++ } else { ++ int id; ++ g_object_get (G_OBJECT (device), "device-id", &id, NULL); ++ g_hash_table_insert (manager->priv->blacklist, ++ GINT_TO_POINTER (id), GINT_TO_POINTER (1)); ++ } ++ } ++ g_list_free (devices); ++ ++ ensure_touchpad_active (manager); ++ + gnome_settings_profile_end (NULL); + + manager->priv->start_idle_id = 0; +@@ -202,6 +1436,11 @@ gsd_mouse_manager_start (GsdMouseManager *manager, + + migrate_mouse_settings (); + ++ if (!supports_xinput_devices ()) { ++ g_debug ("XInput is not supported, not applying any settings"); ++ return TRUE; ++ } ++ + if (gnome_settings_is_wayland ()) + return TRUE; + +@@ -225,9 +1464,16 @@ gsd_mouse_manager_stop (GsdMouseManager *manager) + manager->priv->start_idle_id = 0; + } + ++ if (p->device_manager != NULL) { ++ g_signal_handler_disconnect (p->device_manager, p->device_added_id); ++ g_signal_handler_disconnect (p->device_manager, p->device_removed_id); ++ p->device_manager = NULL; ++ } ++ + g_clear_object (&p->mouse_a11y_settings); + g_clear_object (&p->mouse_settings); + g_clear_object (&p->touchpad_settings); ++ g_clear_object (&p->trackball_settings); + g_clear_object (&p->gsd_mouse_settings); + + set_locate_pointer (manager, FALSE); +@@ -247,6 +1493,9 @@ gsd_mouse_manager_finalize (GObject *object) + + gsd_mouse_manager_stop (mouse_manager); + ++ if (mouse_manager->priv->blacklist != NULL) ++ g_hash_table_destroy (mouse_manager->priv->blacklist); ++ + G_OBJECT_CLASS (gsd_mouse_manager_parent_class)->finalize (object); + } + +-- +2.6.2 + + +From 4b1ed6c7aec9dea2b70fe19c0156fed72899eba6 Mon Sep 17 00:00:00 2001 +From: Frederic Crozat +Date: Fri, 4 Mar 2016 15:49:20 +0100 +Subject: [PATCH 2/3] Revert "common: Remove unused functions" + +This reverts commit 9287ef9ac5b119abdcbbabd920c19f353e577f90. +--- + plugins/common/gsd-input-helper.c | 279 +++++++++++++++++++++++++++++++++++++ + plugins/common/gsd-input-helper.h | 15 ++ + plugins/common/test-input-helper.c | 5 +- + 3 files changed, 298 insertions(+), 1 deletion(-) + +diff --git a/plugins/common/gsd-input-helper.c b/plugins/common/gsd-input-helper.c +index 077ff1c..4dca795 100644 +--- a/plugins/common/gsd-input-helper.c ++++ b/plugins/common/gsd-input-helper.c +@@ -115,6 +115,12 @@ supports_xinput_devices_with_opcode (int *opcode) + } + + gboolean ++supports_xinput_devices (void) ++{ ++ return supports_xinput_devices_with_opcode (NULL); ++} ++ ++gboolean + supports_xtest (void) + { + gint op_code, event, error; +@@ -154,6 +160,66 @@ supports_xinput2_devices (int *opcode) + return TRUE; + } + ++gboolean ++xdevice_is_synaptics (XDevice *xdevice) ++{ ++ Atom realtype, prop; ++ int realformat; ++ unsigned long nitems, bytes_after; ++ unsigned char *data; ++ ++ /* we don't check on the type being XI_TOUCHPAD here, ++ * but having a "Synaptics Off" property should be enough */ ++ ++ prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Off", False); ++ if (!prop) ++ return FALSE; ++ ++ gdk_error_trap_push (); ++ if ((XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop, 0, 1, False, ++ XA_INTEGER, &realtype, &realformat, &nitems, ++ &bytes_after, &data) == Success) && (realtype != None)) { ++ gdk_error_trap_pop_ignored (); ++ XFree (data); ++ return TRUE; ++ } ++ gdk_error_trap_pop_ignored (); ++ ++ return FALSE; ++} ++ ++gboolean ++synaptics_is_present (void) ++{ ++ XDeviceInfo *device_info; ++ gint n_devices; ++ guint i; ++ gboolean retval; ++ ++ retval = FALSE; ++ ++ device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices); ++ if (device_info == NULL) ++ return FALSE; ++ ++ for (i = 0; i < n_devices; i++) { ++ XDevice *device; ++ ++ gdk_error_trap_push (); ++ device = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device_info[i].id); ++ if (gdk_error_trap_pop () || (device == NULL)) ++ continue; ++ ++ retval = xdevice_is_synaptics (device); ++ xdevice_close (device); ++ if (retval) ++ break; ++ } ++ XFreeDeviceList (device_info); ++ ++ return retval; ++} ++ + static gboolean + device_type_is_present (GsdDeviceType type) + { +@@ -181,6 +247,29 @@ mouse_is_present (void) + return device_type_is_present (GSD_DEVICE_TYPE_MOUSE); + } + ++gboolean ++trackball_is_present (void) ++{ ++ gboolean retval = FALSE; ++ GList *l, *mice = gsd_device_manager_list_devices (gsd_device_manager_get (), ++ GSD_DEVICE_TYPE_MOUSE); ++ if (mice == NULL) ++ return FALSE; ++ ++ for (l = mice; l != NULL; l = l->next) { ++ gchar *lowercase; ++ const gchar *name = gsd_device_get_name (l->data); ++ if (!name) ++ continue; ++ lowercase = g_ascii_strdown (name, -1); ++ retval = strstr (lowercase, "trackball") != NULL; ++ g_free (lowercase); ++ } ++ ++ g_list_free (mice); ++ return retval; ++} ++ + char * + xdevice_get_device_node (int deviceid) + { +@@ -339,6 +428,172 @@ set_device_enabled (int device_id, + return TRUE; + } + ++gboolean ++set_synaptics_device_enabled (int device_id, ++ gboolean enabled) ++{ ++ Atom prop; ++ guchar value; ++ ++ prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Off", False); ++ if (!prop) ++ return FALSE; ++ ++ gdk_error_trap_push (); ++ ++ value = enabled ? 0 : 1; ++ XIChangeProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), ++ device_id, prop, XA_INTEGER, 8, PropModeReplace, &value, 1); ++ ++ if (gdk_error_trap_pop ()) ++ return FALSE; ++ ++ return TRUE; ++} ++ ++static const char * ++custom_command_to_string (CustomCommand command) ++{ ++ switch (command) { ++ case COMMAND_DEVICE_ADDED: ++ return "added"; ++ case COMMAND_DEVICE_REMOVED: ++ return "removed"; ++ case COMMAND_DEVICE_PRESENT: ++ return "present"; ++ default: ++ g_assert_not_reached (); ++ } ++} ++ ++/* Run a custom command on device presence events. Parameters passed into ++ * the custom command are: ++ * command -t [added|removed|present] -i ++ * Type 'added' and 'removed' signal 'device added' and 'device removed', ++ * respectively. Type 'present' signals 'device present at ++ * gnome-settings-daemon init'. ++ * ++ * The script is expected to run synchronously, and an exit value ++ * of "1" means that no other settings will be applied to this ++ * particular device. ++ * ++ * More options may be added in the future. ++ * ++ * This function returns TRUE if we should not apply any more settings ++ * to the device. ++ */ ++gboolean ++run_custom_command (GdkDevice *device, ++ CustomCommand command) ++{ ++ GSettings *settings; ++ GError *error = NULL; ++ char *cmd; ++ char *argv[7]; ++ int exit_status; ++ gboolean rc; ++ int id; ++ char *out; ++ ++ settings = g_settings_new (INPUT_DEVICES_SCHEMA); ++ cmd = g_settings_get_string (settings, KEY_HOTPLUG_COMMAND); ++ g_object_unref (settings); ++ ++ if (!cmd || cmd[0] == '\0') { ++ g_free (cmd); ++ return FALSE; ++ } ++ ++ /* Easter egg! */ ++ g_object_get (device, "device-id", &id, NULL); ++ ++ argv[0] = cmd; ++ argv[1] = "-t"; ++ argv[2] = (char *) custom_command_to_string (command); ++ argv[3] = "-i"; ++ argv[4] = g_strdup_printf ("%d", id); ++ argv[5] = (char*) gdk_device_get_name (device); ++ argv[6] = NULL; ++ ++ out = g_strjoinv (" ", argv); ++ g_debug ("About to launch command: %s", out); ++ g_free (out); ++ ++ rc = g_spawn_sync (g_get_home_dir (), argv, NULL, G_SPAWN_SEARCH_PATH, ++ NULL, NULL, NULL, NULL, &exit_status, &error); ++ ++ if (rc == FALSE) { ++ g_warning ("Couldn't execute command '%s', verify that this is a valid command: %s", cmd, error->message); ++ g_clear_error (&error); ++ } ++ ++ g_free (argv[0]); ++ g_free (argv[4]); ++ ++ if (!g_spawn_check_exit_status (exit_status, &error)) { ++ if (g_error_matches (error, G_SPAWN_EXIT_ERROR, 1)) { ++ g_clear_error (&error); ++ return TRUE; ++ } ++ g_clear_error (&error); ++ } ++ ++ return FALSE; ++} ++ ++GList * ++get_disabled_synaptics (void) ++{ ++ GdkDisplay *display; ++ XDeviceInfo *device_info; ++ gint n_devices, act_format, rc; ++ guint i; ++ GList *ret; ++ Atom prop, act_type; ++ unsigned long nitems, bytes_after; ++ unsigned char *data; ++ ++ ret = NULL; ++ ++ display = gdk_display_get_default (); ++ prop = gdk_x11_get_xatom_by_name ("Synaptics Off"); ++ ++ gdk_error_trap_push (); ++ ++ device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (display), &n_devices); ++ if (device_info == NULL) { ++ gdk_error_trap_pop_ignored (); ++ ++ return ret; ++ } ++ ++ for (i = 0; i < n_devices; i++) { ++ rc = XIGetProperty (GDK_DISPLAY_XDISPLAY (display), ++ device_info[i].id, prop, 0, 1, False, ++ XA_INTEGER, &act_type, &act_format, ++ &nitems, &bytes_after, &data); ++ ++ if (rc != Success || act_type != XA_INTEGER || ++ act_format != 8 || nitems < 1) ++ continue; ++ ++ if (!(data[0])) { ++ XFree (data); ++ continue; ++ } ++ ++ XFree (data); ++ ++ ret = g_list_prepend (ret, GINT_TO_POINTER (device_info[i].id)); ++ } ++ ++ gdk_error_trap_pop_ignored (); ++ ++ XFreeDeviceList (device_info); ++ ++ return ret; ++} ++ + const char * + xdevice_get_wacom_tool_type (int deviceid) + { +@@ -425,3 +680,27 @@ xdevice_get_dimensions (int deviceid, + + return (w != 0 && h != 0); + } ++ ++gboolean ++xdevice_is_libinput (gint deviceid) ++{ ++ GdkDisplay *display = gdk_display_get_default (); ++ gulong nitems, bytes_after; ++ gint rc, format; ++ guchar *data; ++ Atom type; ++ ++ gdk_error_trap_push (); ++ ++ /* Lookup a libinput driver specific property */ ++ rc = XIGetProperty (GDK_DISPLAY_XDISPLAY (display), deviceid, ++ gdk_x11_get_xatom_by_name ("libinput Send Events Mode Enabled"), ++ 0, 1, False, XA_INTEGER, &type, &format, &nitems, &bytes_after, &data); ++ ++ if (rc == Success) ++ XFree (data); ++ ++ gdk_error_trap_pop_ignored (); ++ ++ return rc == Success && nitems > 0; ++} +diff --git a/plugins/common/gsd-input-helper.h b/plugins/common/gsd-input-helper.h +index 31e2e47..85e6d07 100644 +--- a/plugins/common/gsd-input-helper.h ++++ b/plugins/common/gsd-input-helper.h +@@ -44,20 +44,32 @@ typedef struct { + } data; + } PropertyHelper; + ++gboolean supports_xinput_devices (void); + gboolean supports_xinput2_devices (int *opcode); + gboolean supports_xtest (void); + + gboolean set_device_enabled (int device_id, + gboolean enabled); + ++gboolean set_synaptics_device_enabled (int device_id, ++ gboolean enabled); ++ ++gboolean xdevice_is_synaptics (XDevice *xdevice); ++ ++gboolean synaptics_is_present (void); + gboolean touchpad_is_present (void); + gboolean touchscreen_is_present (void); + gboolean mouse_is_present (void); ++gboolean trackball_is_present (void); + + gboolean device_set_property (XDevice *xdevice, + const char *device_name, + PropertyHelper *property); + ++gboolean run_custom_command (GdkDevice *device, ++ CustomCommand command); ++ ++GList * get_disabled_synaptics (void); + char * xdevice_get_device_node (int deviceid); + int xdevice_get_last_tool_id (int deviceid); + gboolean xdevice_get_dimensions (int deviceid, +@@ -67,6 +79,9 @@ void xdevice_close (XDevice *xdevice); + + const char * xdevice_get_wacom_tool_type (int deviceid); + ++gboolean xdevice_is_libinput (gint deviceid); ++ ++ + G_END_DECLS + + #endif /* __GSD_INPUT_HELPER_H */ +diff --git a/plugins/common/test-input-helper.c b/plugins/common/test-input-helper.c +index 954ac30..e78f463 100644 +--- a/plugins/common/test-input-helper.c ++++ b/plugins/common/test-input-helper.c +@@ -32,7 +32,7 @@ + int main (int argc, char **argv) + { + GList *devices, *l; +- gboolean has_touchpad, has_touchscreen; ++ gboolean has_touchpad, has_touchscreen, has_trackball; + + gtk_init (&argc, &argv); + +@@ -42,6 +42,9 @@ int main (int argc, char **argv) + has_touchscreen = touchscreen_is_present (); + g_print ("Has touchscreen:\t\t\t%s\n", has_touchscreen ? "yes" : "no"); + ++ has_trackball = trackball_is_present (); ++ g_print ("Has trackball:\t\t\t\t%s\n", has_trackball ? "yes" : "no"); ++ + devices = gsd_device_manager_list_devices (gsd_device_manager_get (), GSD_DEVICE_TYPE_MOUSE); + for (l = devices; l != NULL; l = l->next) + g_print ("Device '%s' is a mouse\n", gsd_device_get_name (l->data)); +-- +2.6.2 + + +From 2e27aeec3c5bcb9fe398bd3835226f261b60baf1 Mon Sep 17 00:00:00 2001 +From: Frederic Crozat +Date: Fri, 4 Mar 2016 15:51:23 +0100 +Subject: [PATCH 3/3] Revert "common: Remove "hotplug-command" helper" + +This reverts commit c50ceb880e928506d987747f9e554079ad3d9826. +--- + ...e.settings-daemon.peripherals.gschema.xml.in.in | 8 +++ + plugins/common/Makefile.am | 3 + + plugins/common/gsd-input-helper.c | 3 + + plugins/common/gsd-input-helper.h | 6 ++ + plugins/common/input-device-example.sh | 69 ++++++++++++++++++++++ + plugins/keyboard/gsd-keyboard-manager.c | 18 ++++++ + 6 files changed, 107 insertions(+) + create mode 100644 plugins/common/input-device-example.sh + +diff --git a/data/org.gnome.settings-daemon.peripherals.gschema.xml.in.in b/data/org.gnome.settings-daemon.peripherals.gschema.xml.in.in +index f4120e9..6a65f08 100644 +--- a/data/org.gnome.settings-daemon.peripherals.gschema.xml.in.in ++++ b/data/org.gnome.settings-daemon.peripherals.gschema.xml.in.in +@@ -4,6 +4,7 @@ + + + ++ + + + +@@ -67,6 +68,13 @@ + <_summary>Whether the tablet's orientation is locked, or rotated automatically. + + ++ ++ ++ '' ++ <_summary>Device hotplug custom command ++ <_description>Command to be run when a device is added or removed. An exit value of 1 means that the device will not be handled further by gnome-settings-daemon. ++ ++ + + + +diff --git a/plugins/common/Makefile.am b/plugins/common/Makefile.am +index 0331226..0f85351 100644 +--- a/plugins/common/Makefile.am ++++ b/plugins/common/Makefile.am +@@ -82,6 +82,9 @@ test_egg_key_parsing_SOURCES = test-egg-key-parsing.c + test_egg_key_parsing_LDADD = libcommon.la $(COMMON_LIBS) + test_egg_key_parsing_CFLAGS = $(libcommon_la_CFLAGS) + ++scriptsdir = $(datadir)/gnome-settings-daemon-@GSD_API_VERSION@ ++scripts_DATA = input-device-example.sh ++ + EXTRA_DIST = $(scripts_DATA) test-plugin.h + + CLEANFILES = \ +diff --git a/plugins/common/gsd-input-helper.c b/plugins/common/gsd-input-helper.c +index 4dca795..e3fe2d8 100644 +--- a/plugins/common/gsd-input-helper.c ++++ b/plugins/common/gsd-input-helper.c +@@ -31,6 +31,9 @@ + #include "gsd-input-helper.h" + #include "gsd-device-manager.h" + ++#define INPUT_DEVICES_SCHEMA "org.gnome.settings-daemon.peripherals.input-devices" ++#define KEY_HOTPLUG_COMMAND "hotplug-command" ++ + #define ABS_MT_X "Abs MT Position X" + #define ABS_MT_Y "Abs MT Position Y" + #define ABS_X "Abs X" +diff --git a/plugins/common/gsd-input-helper.h b/plugins/common/gsd-input-helper.h +index 85e6d07..aadd790 100644 +--- a/plugins/common/gsd-input-helper.h ++++ b/plugins/common/gsd-input-helper.h +@@ -28,6 +28,12 @@ G_BEGIN_DECLS + + #define WACOM_SERIAL_IDS_PROP "Wacom Serial IDs" + ++typedef enum { ++ COMMAND_DEVICE_ADDED, ++ COMMAND_DEVICE_REMOVED, ++ COMMAND_DEVICE_PRESENT ++} CustomCommand; ++ + /* Generic property setting code. Fill up the struct property with the property + * data and pass it into device_set_property together with the device to be + * changed. Note: doesn't cater for non-zero offsets yet, but we don't have +diff --git a/plugins/common/input-device-example.sh b/plugins/common/input-device-example.sh +new file mode 100644 +index 0000000..235cdc4 +--- /dev/null ++++ b/plugins/common/input-device-example.sh +@@ -0,0 +1,69 @@ ++#!/bin/sh ++# ++# This script is an example hotplug script for use with the various ++# input devices plugins. ++# ++# The script is called with the arguments: ++# -t [added|present|removed] ++# added ... device was just plugged in ++# present.. device was present at gnome-settings-daemon startup ++# removed.. device was just removed ++# -i ++# device ID being the XInput device ID ++# The name of the device ++# ++# The script should return 1 if the device is to be ++# ignored from future configuration. ++# ++# Set the script to be used with: ++# gsettings set org.gnome.settings-daemon.peripherals.input-devices hotplug-command /path/to/script/input-devices.sh ++# ++ ++args=`getopt "t:i:" $*` ++ ++set -- $args ++ ++while [ $# -gt 0 ] ++do ++ case $1 in ++ -t) ++ shift; ++ type="$1" ++ ;; ++ -i) ++ shift; ++ id="$1" ++ ;; ++ --) ++ shift; ++ device="$@" ++ break; ++ ;; ++ *) ++ echo "Unknown option $1"; ++ exit 1 ++ ;; ++ esac ++ shift ++done ++ ++retval=0 ++ ++case $type in ++ added) ++ echo "Device '$device' (ID=$id) was added" ++ ;; ++ present) ++ echo "Device '$device' (ID=$id) was already present at startup" ++ ;; ++ removed) ++ echo "Device '$device' (ID=$id) was removed" ++ ;; ++ *) ++ echo "Unknown operation" ++ retval=1 ++ ;; ++esac ++ ++# All further processing will be disabled if $retval == 1 ++exit $retval +diff --git a/plugins/keyboard/gsd-keyboard-manager.c b/plugins/keyboard/gsd-keyboard-manager.c +index ddeeee6..eb75c92 100644 +--- a/plugins/keyboard/gsd-keyboard-manager.c ++++ b/plugins/keyboard/gsd-keyboard-manager.c +@@ -90,6 +90,7 @@ struct GsdKeyboardManagerPrivate + GsdNumLockState old_state; + GdkDeviceManager *device_manager; + guint device_added_id; ++ guint device_removed_id; + }; + + static void gsd_keyboard_manager_class_init (GsdKeyboardManagerClass *klass); +@@ -363,6 +364,20 @@ device_added_cb (GdkDeviceManager *device_manager, + if (source == GDK_SOURCE_KEYBOARD) { + g_debug ("New keyboard plugged in, applying all settings"); + apply_numlock (manager); ++ run_custom_command (device, COMMAND_DEVICE_ADDED); ++ } ++} ++ ++static void ++device_removed_cb (GdkDeviceManager *device_manager, ++ GdkDevice *device, ++ GsdKeyboardManager *manager) ++{ ++ GdkInputSource source; ++ ++ source = gdk_device_get_source (device); ++ if (source == GDK_SOURCE_KEYBOARD) { ++ run_custom_command (device, COMMAND_DEVICE_REMOVED); + } + } + +@@ -378,6 +393,8 @@ set_devicepresence_handler (GsdKeyboardManager *manager) + + manager->priv->device_added_id = g_signal_connect (G_OBJECT (device_manager), "device-added", + G_CALLBACK (device_added_cb), manager); ++ manager->priv->device_removed_id = g_signal_connect (G_OBJECT (device_manager), "device-removed", ++ G_CALLBACK (device_removed_cb), manager); + manager->priv->device_manager = device_manager; + } + +@@ -758,6 +775,7 @@ gsd_keyboard_manager_stop (GsdKeyboardManager *manager) + + if (p->device_manager != NULL) { + g_signal_handler_disconnect (p->device_manager, p->device_added_id); ++ g_signal_handler_disconnect (p->device_manager, p->device_removed_id); + p->device_manager = NULL; + } + +-- +2.6.2 + diff --git a/gnome-settings-daemon.changes b/gnome-settings-daemon.changes index dd38650..27bdefb 100644 --- a/gnome-settings-daemon.changes +++ b/gnome-settings-daemon.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Fri Mar 4 12:57:15 UTC 2016 - fcrozat@suse.com + +- Add gnome-settings-daemon-revert-libinput-mandatory.patch: do not + force libinput driver on SLE. +- Re-add "hotplug-command" helper when building for SLE. + ------------------------------------------------------------------- Thu Mar 3 21:57:28 UTC 2016 - zaitor@opensuse.org diff --git a/gnome-settings-daemon.spec b/gnome-settings-daemon.spec index b66fe4d..14451fb 100644 --- a/gnome-settings-daemon.spec +++ b/gnome-settings-daemon.spec @@ -37,8 +37,10 @@ License: GPL-2.0+ Group: System/GUI/GNOME Url: http://www.gnome.org Source: http://download.gnome.org/sources/gnome-settings-daemon/3.19/%{name}-%{version}.tar.xz +# PATCH-FEATURE-SLE gnome-settings-daemon-revert-libinput-mandatory.patch fcrozat@suse.com -- ensure libinput is not mandatory +Patch20: gnome-settings-daemon-revert-libinput-mandatory.patch # PATCH-FEATURE-SLE gnome-settings-daemon-notify-idle-resumed.patch bnc#439018 bnc#708182 bgo#575467 hpj@suse.com -- notify user about auto suspend when returning from sleep -Patch19: gnome-settings-daemon-notify-idle-resumed.patch +Patch21: gnome-settings-daemon-notify-idle-resumed.patch BuildRequires: cups-devel BuildRequires: fdupes BuildRequires: gnome-common @@ -131,7 +133,8 @@ contact the settings daemon via its DBus interface. translation-update-upstream # Disabled because of the non-rebased patch #gnome-patch-translation-prepare -%patch19 -p1 +%patch20 -p1 +%patch21 -p1 %endif %build @@ -174,6 +177,9 @@ rm -rf %{buildroot} %defattr(-,root,root) %doc AUTHORS COPYING ChangeLog NEWS %{_datadir}/gnome-settings-daemon/ +%if !0%{?is_opensuse} +%{_datadir}/gnome-settings-daemon-3.0/ +%endif %dir %{_libexecdir}/gnome-settings-daemon-3.0/ %{_libexecdir}/gnome-settings-daemon-3.0/gnome-settings-daemon %{_libexecdir}/gnome-settings-daemon-3.0/gnome-settings-daemon-localeexec