forked from 12to11/12to11
Fix scroll axis interpolation with the libinput driver
* atoms.c (names, XLInitAtoms): Intern "libinput Scrolling Pixel Distance". * compositor.h: Update atom. * seat.c (struct _DeviceInfo): New field `scroll_pixel_distance'. (UpdateScrollPixelDistance): New function. (RecordDeviceInformation, HandlePropertyChanged): Update that field whenever necessary. (InterpolateAxes, SendScrollAxis): Fix NULL pointer dereference and always interpolate axes by the scroll pixel distance whenever available. (HandleValuatorMotion): Don't scale axis values by 10.
This commit is contained in:
parent
b0db38043a
commit
a220f29723
3 changed files with 76 additions and 18 deletions
6
atoms.c
6
atoms.c
|
@ -111,6 +111,7 @@ static const char *names[] =
|
|||
"CONNECTOR_ID",
|
||||
"_NET_WM_PID",
|
||||
"_NET_WM_PING",
|
||||
"libinput Scrolling Pixel Distance",
|
||||
|
||||
/* These are automatically generated from mime.txt. */
|
||||
DirectTransferAtomNames
|
||||
|
@ -133,7 +134,7 @@ Atom _NET_WM_OPAQUE_REGION, _XL_BUFFER_RELEASE, _NET_WM_SYNC_REQUEST_COUNTER,
|
|||
XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished,
|
||||
_NET_WM_FRAME_TIMINGS, _NET_WM_BYPASS_COMPOSITOR, WM_STATE,
|
||||
_NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_MENU, _NET_WM_WINDOW_TYPE_DND,
|
||||
CONNECTOR_ID, _NET_WM_PID, _NET_WM_PING;
|
||||
CONNECTOR_ID, _NET_WM_PID, _NET_WM_PING, libinput_Scrolling_Pixel_Distance;
|
||||
|
||||
XrmQuark resource_quark, app_quark, QString;
|
||||
|
||||
|
@ -290,9 +291,10 @@ XLInitAtoms (void)
|
|||
CONNECTOR_ID = atoms[61];
|
||||
_NET_WM_PID = atoms[62];
|
||||
_NET_WM_PING = atoms[63];
|
||||
libinput_Scrolling_Pixel_Distance = atoms[64];
|
||||
|
||||
/* This is automatically generated. */
|
||||
DirectTransferAtomInit (atoms, 64);
|
||||
DirectTransferAtomInit (atoms, 65);
|
||||
|
||||
/* Now, initialize quarks. */
|
||||
resource_quark = XrmPermStringToQuark (compositor.resource_name);
|
||||
|
|
|
@ -1177,7 +1177,7 @@ extern Atom _NET_WM_OPAQUE_REGION, _XL_BUFFER_RELEASE,
|
|||
XdndProxy, XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop,
|
||||
XdndFinished, _NET_WM_FRAME_TIMINGS, _NET_WM_BYPASS_COMPOSITOR, WM_STATE,
|
||||
_NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_MENU, _NET_WM_WINDOW_TYPE_DND,
|
||||
CONNECTOR_ID, _NET_WM_PID, _NET_WM_PING;
|
||||
CONNECTOR_ID, _NET_WM_PID, _NET_WM_PING, libinput_Scrolling_Pixel_Distance;
|
||||
|
||||
extern XrmQuark resource_quark, app_quark, QString;
|
||||
|
||||
|
|
86
seat.c
86
seat.c
|
@ -565,6 +565,9 @@ struct _DeviceInfo
|
|||
{
|
||||
/* Some flags associated with this device. */
|
||||
int flags;
|
||||
|
||||
/* The libinput scroll pixel distance, if available. Else 15. */
|
||||
int scroll_pixel_distance;
|
||||
};
|
||||
|
||||
#define SetMask(ptr, event) \
|
||||
|
@ -1918,6 +1921,44 @@ UpdateScrollMethods (DeviceInfo *info, int deviceid)
|
|||
XFree (data);
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateScrollPixelDistance (DeviceInfo *info, int deviceid)
|
||||
{
|
||||
unsigned char *data;
|
||||
Status rc;
|
||||
Atom actual_type;
|
||||
int actual_format;
|
||||
unsigned long nitems, bytes_after;
|
||||
|
||||
data = NULL;
|
||||
|
||||
/* This only works with the libinput driver. */
|
||||
rc = XIGetProperty (compositor.display, deviceid,
|
||||
libinput_Scrolling_Pixel_Distance,
|
||||
0, 1, False, XIAnyPropertyType,
|
||||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &data);
|
||||
|
||||
/* If there aren't enough items in the data, or the format is wrong,
|
||||
return. */
|
||||
if (rc != Success || nitems < 1 || actual_format != 32 || !data)
|
||||
{
|
||||
if (data)
|
||||
XFree (data);
|
||||
|
||||
/* Set the distance to the default, 15. */
|
||||
info->scroll_pixel_distance = 15;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now set the scroll pixel distance. */
|
||||
info->scroll_pixel_distance = ((long *) data)[0];
|
||||
|
||||
/* And free the data. */
|
||||
XLFree (data);
|
||||
}
|
||||
|
||||
static void
|
||||
RecordDeviceInformation (XIDeviceInfo *deviceinfo)
|
||||
{
|
||||
|
@ -1946,6 +1987,10 @@ RecordDeviceInformation (XIDeviceInfo *deviceinfo)
|
|||
only works with the libinput driver. */
|
||||
UpdateScrollMethods (info, deviceinfo->deviceid);
|
||||
|
||||
/* Obtain the "libinput Scrolling Pixel Distance" property and
|
||||
use it if available. If not, default to 15. */
|
||||
UpdateScrollPixelDistance (info, deviceinfo->deviceid);
|
||||
|
||||
/* Uncatch errors. */
|
||||
UncatchXErrors (NULL);
|
||||
}
|
||||
|
@ -2602,6 +2647,9 @@ HandlePropertyChanged (XIPropertyEvent *event)
|
|||
/* Update scroll methods for the device whose property
|
||||
changed. */
|
||||
UpdateScrollMethods (info, event->deviceid);
|
||||
else if (event->property == libinput_Scrolling_Pixel_Distance)
|
||||
/* Update the scroll pixel distance. */
|
||||
UpdateScrollPixelDistance (info, event->deviceid);
|
||||
}
|
||||
|
||||
static Seat *
|
||||
|
@ -3705,15 +3753,21 @@ FindScrollValuator (Seat *seat, int number)
|
|||
}
|
||||
|
||||
static void
|
||||
InterpolateAxes (Surface *surface, double movement_x,
|
||||
double movement_y, double *x_out,
|
||||
double *y_out)
|
||||
InterpolateAxes (Surface *surface, DeviceInfo *info,
|
||||
double movement_x, double movement_y,
|
||||
double *x_out, double *y_out)
|
||||
{
|
||||
/* This is the algorithm used by most programs. */
|
||||
*x_out = movement_x * pow (ViewWidth (surface->view),
|
||||
2.0 / 3.0);
|
||||
*x_out = movement_y * pow (ViewHeight (surface->view),
|
||||
2.0 / 3.0);
|
||||
if (!info)
|
||||
{
|
||||
/* Multiply the deltas by 15 if no device was found. */
|
||||
*x_out = movement_x * 15;
|
||||
*y_out = movement_y * 15;
|
||||
}
|
||||
|
||||
/* Multiply these deltas by the scrolling pixel distance to obtain
|
||||
the original delta. */
|
||||
*x_out = movement_x * info->scroll_pixel_distance;
|
||||
*y_out = movement_y * info->scroll_pixel_distance;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -3749,12 +3803,14 @@ SendScrollAxis (Seat *seat, Surface *surface, Time time,
|
|||
if (wl_resource_get_version (pointer->resource) < 8
|
||||
/* Send pixel-wise axis events from devices that are most
|
||||
likely touchpads. */
|
||||
|| (deviceinfo->flags & DeviceCanFingerScroll
|
||||
|| deviceinfo->flags & DeviceCanEdgeScroll))
|
||||
|| (deviceinfo
|
||||
&& (deviceinfo->flags & DeviceCanFingerScroll
|
||||
|| deviceinfo->flags & DeviceCanEdgeScroll)))
|
||||
{
|
||||
/* Interpolate the increment-relative axis values to pixel
|
||||
values. */
|
||||
InterpolateAxes (surface, axis_x, axis_y, &axis_x, &axis_y);
|
||||
InterpolateAxes (surface, deviceinfo, axis_x, axis_y,
|
||||
&axis_x, &axis_y);
|
||||
|
||||
if (axis_x != 0.0)
|
||||
wl_pointer_send_axis (pointer->resource, time,
|
||||
|
@ -3774,12 +3830,12 @@ SendScrollAxis (Seat *seat, Surface *surface, Time time,
|
|||
if (axis_x != 0.0)
|
||||
wl_pointer_send_axis_value120 (pointer->resource,
|
||||
WL_POINTER_AXIS_HORIZONTAL_SCROLL,
|
||||
axis_x * 12);
|
||||
axis_x * 120);
|
||||
|
||||
if (axis_y != 0.0)
|
||||
wl_pointer_send_axis_value120 (pointer->resource,
|
||||
WL_POINTER_AXIS_VERTICAL_SCROLL,
|
||||
axis_y * 12);
|
||||
axis_y * 120);
|
||||
}
|
||||
|
||||
if (axis_y == 0.0 && axis_x == 0.0)
|
||||
|
@ -3862,8 +3918,8 @@ HandleValuatorMotion (Seat *seat, Surface *dispatch, double x, double y,
|
|||
}
|
||||
|
||||
if (value && dispatch)
|
||||
SendScrollAxis (seat, dispatch, event->time, x, y,
|
||||
total_x * 10, total_y * 10, flags,
|
||||
SendScrollAxis (seat, dispatch, event->time, x, y, total_x,
|
||||
total_y, flags,
|
||||
/* Also pass the event source device ID, which is
|
||||
used in an attempt to determine the axis
|
||||
source. */
|
||||
|
|
Loading…
Add table
Reference in a new issue