Commit 49be65f8 authored by Olivier Fourdan's avatar Olivier Fourdan 🛠 Committed by Olivier Fourdan

Add support for libinput Xorg driver

Bug: 11469
Signed-off-by: Olivier Fourdan's avatarOlivier Fourdan <fourdan@xfce.org>
parent 5a7f55a0
......@@ -158,6 +158,12 @@ dnl ************************************
XDT_CHECK_OPTIONAL_PACKAGE([XCURSOR], [xcursor], [1.1.0],
[xcursor], [Cursor themes support])
dnl *************************************************
dnl *** Optional support for libinput Xorg driver ***
dnl *************************************************
XDT_CHECK_OPTIONAL_PACKAGE([LIBINPUT], [xorg-libinput], [0.6.0],
[xorg-libinput], [libinput Xorg driver support])
dnl ****************************************
dnl *** Optional support for Libxklavier ***
dnl ****************************************
......@@ -272,6 +278,11 @@ echo "* Xcursor support: yes"
else
echo "* Xcursor support: no"
fi
if test x"$LIBINPUT_FOUND" = x"yes"; then
echo "* Xorg libinput support: yes"
else
echo "* Xorg libinput support: no"
fi
if test x"$ENABLE_PLUGGABLE_DIALOGS" = x"1"; then
echo "* Embedded settings dialogs yes"
else
......
......@@ -23,6 +23,7 @@ xfce4_mouse_settings_CFLAGS = \
$(XI_CFLAGS) \
$(XFCONF_CFLAGS) \
$(LIBX11_CFLAGS) \
$(LIBINPUT_CFLAGS) \
$(PLATFORM_CFLAGS)
xfce4_mouse_settings_LDFLAGS = \
......@@ -36,6 +37,7 @@ xfce4_mouse_settings_LDADD = \
$(XFCONF_LIBS) \
$(XI_LIBS) \
$(LIBX11_LIBS) \
$(LIBINPUT_LIBS) \
-lm
if HAVE_XCURSOR
......
......@@ -36,6 +36,10 @@
#include <X11/Xcursor/Xcursor.h>
#endif /* !HAVE_XCURSOR */
#ifdef HAVE_LIBINPUT
#include "libinput-properties.h"
#endif /* HAVE_LIBINPUT */
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
......@@ -114,7 +118,17 @@ enum
N_DEVICE_COLUMNS
};
typedef union
{
gchar c;
guchar uc;
gint16 i16;
guint16 u16;
gint32 i32;
guint32 u32;
float f;
Atom a;
} propdata_t;
static gchar *
mouse_settings_format_value_px (GtkScale *scale,
......@@ -576,6 +590,128 @@ mouse_settings_themes_populate_store (GtkBuilder *builder)
#ifdef HAVE_LIBINPUT
/* FIXME: Completely overkill here and better suited in some common file */
static gboolean
mouse_settings_get_device_prop (Display *xdisplay,
XDevice *device,
const gchar *prop_name,
Atom type,
propdata_t *retval)
{
Atom prop, float_type, type_ret;
gulong n_items, bytes_after;
gint rc, format;
guchar *data;
gboolean success;
prop = XInternAtom (xdisplay, prop_name, False);
float_type = XInternAtom (xdisplay, "FLOAT", False);
gdk_error_trap_push ();
rc = XGetDeviceProperty (xdisplay, device, prop, 0, 1, False,
type, &type_ret, &format, &n_items,
&bytes_after, &data);
gdk_error_trap_pop ();
if (rc == Success && type_ret == type && n_items > 0)
{
success = TRUE;
switch (type_ret)
{
case XA_INTEGER:
switch (format)
{
case 8:
retval->c = *((gchar*) data);
break;
case 16:
retval->i16 = *((gint16 *) data);
break;
case 32:
retval->i32 = *((gint32 *) data);
break;
}
break;
case XA_CARDINAL:
switch (format)
{
case 8:
retval->uc = *((guchar*) data);
break;
case 16:
retval->u16 = *((guint16 *) data);
break;
case 32:
retval->u32 = *((guint32 *) data);
break;
}
break;
case XA_ATOM:
retval->a = *((Atom *) data);
break;
default:
if (type_ret == float_type)
{
retval->f = *((float*) data);
}
else
{
success = FALSE;
g_warning ("Unhandled type, please implement it");
}
break;
}
XFree (data);
return success;
}
return FALSE;
}
static gboolean
mouse_settings_get_libinput_accel (Display *xdisplay,
XDevice *device,
gdouble *val)
{
propdata_t pdata;
Atom float_type;
float_type = XInternAtom (xdisplay, "FLOAT", False);
if (mouse_settings_get_device_prop (xdisplay, device, LIBINPUT_PROP_ACCEL, float_type, &pdata))
{
/* We use double internally, for whatever reason */
*val = (gdouble) (pdata.f + 1.0) * 5.0;
return TRUE;
}
return FALSE;
}
static gboolean
mouse_settings_get_libinput_boolean (Display *xdisplay,
XDevice *device,
const gchar *prop_name,
gboolean *val)
{
propdata_t pdata;
if (mouse_settings_get_device_prop (xdisplay, device, prop_name, XA_INTEGER, &pdata))
{
*val = (gboolean) (pdata.c);
return TRUE;
}
return FALSE;
}
#endif /* HAVE_LIBINPUT */
#ifdef DEVICE_PROPERTIES
static gint
mouse_settings_device_get_int_property (XDevice *device,
......@@ -989,6 +1125,9 @@ mouse_settings_device_selection_changed (GtkBuilder *builder)
gint ndevices;
gboolean is_synaptics = FALSE;
gboolean is_wacom = FALSE;
gboolean is_libinput = FALSE;
gboolean left_handed = FALSE;
gboolean reverse_scrolling = FALSE;
#ifdef DEVICE_PROPERTIES
Atom synaptics_prop;
Atom wacom_prop;
......@@ -1047,63 +1186,73 @@ mouse_settings_device_selection_changed (GtkBuilder *builder)
XFreeDeviceList (device_info);
}
/* get the button mapping */
if (nbuttons > 0)
#ifdef HAVE_LIBINPUT
is_libinput = mouse_settings_get_libinput_boolean (xdisplay, device, LIBINPUT_PROP_LEFT_HANDED, &left_handed);
mouse_settings_get_libinput_boolean (xdisplay, device, LIBINPUT_PROP_NATURAL_SCROLL, &reverse_scrolling);
if (!is_libinput)
#endif /* HAVE_LIBINPUT */
{
buttonmap = g_new0 (guchar, nbuttons);
gdk_error_trap_push ();
XGetDeviceButtonMapping (xdisplay, device, buttonmap, nbuttons);
if (gdk_error_trap_pop () != 0)
g_critical ("Failed to get button map");
/* figure out the position of the first and second/third button in the map */
for (i = 0; i < nbuttons; i++)
/* get the button mapping */
if (nbuttons > 0)
{
buttonmap = g_new0 (guchar, nbuttons);
gdk_error_trap_push ();
XGetDeviceButtonMapping (xdisplay, device, buttonmap, nbuttons);
if (gdk_error_trap_pop () != 0)
g_critical ("Failed to get button map");
/* figure out the position of the first and second/third button in the map */
for (i = 0; i < nbuttons; i++)
{
if (buttonmap[i] == 1)
id_1 = i;
else if (buttonmap[i] == (nbuttons < 3 ? 2 : 3))
id_3 = i;
else if (buttonmap[i] == 4)
id_4 = i;
else if (buttonmap[i] == 5)
id_5 = i;
}
g_free (buttonmap);
left_handed = (id_1 > id_3);
reverse_scrolling = !!(id_5 < id_4);
}
else
{
if (buttonmap[i] == 1)
id_1 = i;
else if (buttonmap[i] == (nbuttons < 3 ? 2 : 3))
id_3 = i;
else if (buttonmap[i] == 4)
id_4 = i;
else if (buttonmap[i] == 5)
id_5 = i;
g_critical ("Device has no buttons");
}
g_free (buttonmap);
}
else
{
g_critical ("Device has no buttons");
}
/* get the feedback states for this device */
gdk_error_trap_push ();
states = XGetFeedbackControl (xdisplay, device, &nstates);
if (gdk_error_trap_pop () != 0 || states == NULL)
{
g_critical ("Failed to get feedback states");
}
else
#ifdef HAVE_LIBINPUT
if (!mouse_settings_get_libinput_accel (xdisplay, device, &acceleration))
#endif /* HAVE_LIBINPUT */
{
/* get the pointer feedback class */
for (pt = states, i = 0; i < nstates; i++)
/* get the feedback states for this device */
gdk_error_trap_push ();
states = XGetFeedbackControl (xdisplay, device, &nstates);
if (gdk_error_trap_pop () != 0 || states == NULL)
{
g_critical ("Failed to get feedback states");
}
else
{
if (pt->class == PtrFeedbackClass)
/* get the pointer feedback class */
for (pt = states, i = 0; i < nstates; i++)
{
/* get the state */
state = (XPtrFeedbackState *) pt;
acceleration = (gdouble) state->accelNum / (gdouble) state->accelDenom;
threshold = state->threshold;
if (pt->class == PtrFeedbackClass)
{
/* get the state */
state = (XPtrFeedbackState *) pt;
acceleration = (gdouble) state->accelNum / (gdouble) state->accelDenom;
threshold = state->threshold;
}
/* advance the offset */
pt = (XFeedbackState *) ((gchar *) pt + pt->length);
}
/* advance the offset */
pt = (XFeedbackState *) ((gchar *) pt + pt->length);
XFreeFeedbackList (states);
}
XFreeFeedbackList (states);
}
#ifdef DEVICE_PROPERTIES
/* wacom and synaptics specific properties */
device_enabled_prop = XInternAtom (xdisplay, "Device Enabled", True);
......@@ -1149,7 +1298,7 @@ mouse_settings_device_selection_changed (GtkBuilder *builder)
}
/* update button order */
object = gtk_builder_get_object (builder, id_1 > id_3 ? "device-left-handed" : "device-right-handed");
object = gtk_builder_get_object (builder, left_handed ? "device-left-handed" : "device-right-handed");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (object), TRUE);
object = gtk_builder_get_object (builder, "device-reverse-scrolling");
......@@ -1164,7 +1313,9 @@ mouse_settings_device_selection_changed (GtkBuilder *builder)
/* update threshold scale */
object = gtk_builder_get_object (builder, "device-threshold-scale");
gtk_range_set_value (GTK_RANGE (object), threshold);
gtk_widget_set_sensitive (GTK_WIDGET (object), threshold != -1);
gtk_widget_set_visible (GTK_WIDGET (object), threshold != -1);
object = gtk_builder_get_object (builder, "device-threshold-label");
gtk_widget_set_visible (GTK_WIDGET (object), threshold != -1);
object = gtk_builder_get_object (builder, "device-enabled");
#ifdef DEVICE_PROPERTIES
......@@ -1177,6 +1328,11 @@ mouse_settings_device_selection_changed (GtkBuilder *builder)
gtk_widget_set_visible (GTK_WIDGET (object), FALSE);
#endif
#ifdef HAVE_LIBINPUT
object = gtk_builder_get_object (builder, "device-reset-feedback");
gtk_widget_set_visible (GTK_WIDGET (object), !is_libinput);
#endif /* HAVE_LIBINPUT */
/* synaptics options */
object = gtk_builder_get_object (builder, "synaptics-tab");
gtk_widget_set_visible (GTK_WIDGET (object), is_synaptics);
......
......@@ -17,10 +17,10 @@
<property name="page_increment">100</property>
</object>
<object class="GtkAdjustment" id="device-acceleration">
<property name="lower">0.10000000000000001</property>
<property name="lower">0</property>
<property name="upper">10</property>
<property name="value">2</property>
<property name="step_increment">0.10000000000000001</property>
<property name="step_increment">0.1</property>
<property name="page_increment">1</property>
</object>
<object class="GtkAdjustment" id="device-threshold">
......@@ -43,10 +43,10 @@
<property name="stock">gtk-revert-to-saved</property>
</object>
<object class="GtkAdjustment" id="synaptics-disable-duration">
<property name="lower">0.10000000000000001</property>
<property name="lower">0.1</property>
<property name="upper">4</property>
<property name="value">2</property>
<property name="step_increment">0.10000000000000001</property>
<property name="step_increment">0.1</property>
<property name="page_increment">1</property>
</object>
<object class="GtkListStore" id="synaptics-scroll-store">
......
......@@ -54,6 +54,7 @@ xfsettingsd_CFLAGS = \
$(LIBX11_CFLAGS) \
$(LIBNOTIFY_CFLAGS) \
$(FONTCONFIG_CFLAGS) \
$(LIBINPUT_CFLAGS) \
$(PLATFORM_CFLAGS)
xfsettingsd_LDFLAGS = \
......@@ -75,6 +76,7 @@ xfsettingsd_LDADD = \
$(LIBX11_LIBS) \
$(LIBNOTIFY_LIBS) \
$(FONTCONFIG_LIBS) \
$(LIBINPUT_LIBS) \
-lm
#
......
......@@ -30,6 +30,10 @@
#include <string.h>
#endif
#ifdef HAVE_LIBINPUT
#include "libinput-properties.h"
#endif /* HAVE_LIBINPUT */
#include <glib.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
......@@ -42,7 +46,6 @@
#include "pointers.h"
#include "pointers-defines.h"
#define MAX_DENOMINATOR (100.00)
#define XFCONF_TYPE_G_VALUE_ARRAY (dbus_g_type_get_collection ("GPtrArray", G_TYPE_VALUE))
......@@ -190,6 +193,65 @@ xfce_pointers_helper_finalize (GObject *object)
#ifdef HAVE_LIBINPUT
static gboolean
xfce_pointers_is_libinput (Display *xdisplay,
XDevice *device)
{
Atom prop, type;
gulong n_items, bytes_after;
gint rc, format;
guchar *data;
prop = XInternAtom (xdisplay, LIBINPUT_PROP_LEFT_HANDED, False);
gdk_error_trap_push ();
rc = XGetDeviceProperty (xdisplay, device, prop, 0, 1, False,
XA_INTEGER, &type, &format, &n_items,
&bytes_after, &data);
gdk_error_trap_pop ();
if (rc == Success)
{
XFree (data);
return (n_items > 0);
}
return FALSE;
}
static void
xfce_pointers_change_property (XDeviceInfo *device_info,
XDevice *device,
Display *xdisplay,
const gchar *prop_name,
Atom type,
int format,
void *data,
gulong nitems)
{
gulong nitems_ret, bytes_after_ret;
gint rc, format_ret;
Atom prop, type_ret;
guchar *data_ret;
prop = XInternAtom (xdisplay, prop_name, False);
rc = XGetDeviceProperty (xdisplay, device, prop, 0, 0, False,
type, &type_ret, &format_ret,
&nitems_ret, &bytes_after_ret, &data_ret);
if (rc == Success)
{
XFree (data_ret);
if (type_ret == type && format_ret == format)
{
XChangeDeviceProperty (xdisplay, device, prop, type,
format, PropModeReplace, data, nitems);
}
}
}
#endif /* HAVE_LIBINPUT */
static void
xfce_pointers_helper_syndaemon_stop (XfcePointersHelper *helper)
{
......@@ -355,6 +417,29 @@ xfce_pointers_helper_change_button_mapping (XDeviceInfo *device_info,
gint right_button;
GString *readable_map;
#ifdef HAVE_LIBINPUT
if (xfce_pointers_is_libinput (xdisplay, device))
{
if (right_handed != -1)
{
gboolean left_handed = !right_handed;
xfce_pointers_change_property (device_info, device, xdisplay,
LIBINPUT_PROP_LEFT_HANDED,
XA_INTEGER, 8, &left_handed, 1);
}
if (reverse_scrolling != -1)
{
xfce_pointers_change_property (device_info, device, xdisplay,
LIBINPUT_PROP_NATURAL_SCROLL,
XA_INTEGER, 8, &reverse_scrolling, 1);
}
return;
}
#endif /* HAVE_LIBINPUT */
/* search the number of buttons */
for (n = 0, ptr = device_info->inputclassinfo; n < device_info->num_classes; n++)
{
......@@ -464,6 +549,20 @@ xfce_pointers_helper_change_feedback (XDeviceInfo *device_info,
gint num, denom, gcd;
gboolean found = FALSE;
#ifdef HAVE_LIBINPUT
if (xfce_pointers_is_libinput (xdisplay, device))
{
gfloat libinput_accel;
libinput_accel = (acceleration / 5) - 1.0;
xfce_pointers_change_property (device_info, device, xdisplay,
LIBINPUT_PROP_ACCEL,
XInternAtom (xdisplay, "FLOAT", False),
32, &libinput_accel, 1);
return;
}
#endif /* HAVE_LIBINPUT */
/* get the feedback states for this device */
gdk_error_trap_push ();
states = XGetFeedbackControl (xdisplay, device, &num_feedbacks);
......@@ -497,9 +596,9 @@ xfce_pointers_helper_change_feedback (XDeviceInfo *device_info,
/* above 0 is a valid value, -1 is reset, -2.00
* is passed if no change is required */
if (acceleration > 0 || acceleration == -1)
if (acceleration >= 0 || acceleration == -1)
{
if (acceleration > 0)
if (acceleration >= 0)
{
/* calculate the faction of the acceleration */
num = acceleration * MAX_DENOMINATOR;
......@@ -642,6 +741,7 @@ xfce_pointers_helper_change_property (XDeviceInfo *device_info,
guchar *c;
gshort *s;
glong *l;
float *f;
Atom *a;
} data;
......@@ -734,7 +834,7 @@ xfce_pointers_helper_change_property (XDeviceInfo *device_info,
&& type == float_atom
&& format == 32)
{
data.l[i] = g_value_get_double (val);
data.f[i] = (float) g_value_get_double (val);
}
else
{
......@@ -771,9 +871,11 @@ xfce_pointers_helper_change_property (XDeviceInfo *device_info,
XFree (props);
}
#endif
#ifdef DEVICE_PROPERTIES
static void
xfce_pointers_helper_change_properties (gpointer key,
gpointer value,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment