diff --git a/include/synaptics-properties.h b/include/synaptics-properties.h index b944adb..8e7b9b1 100644 --- a/include/synaptics-properties.h +++ b/include/synaptics-properties.h @@ -149,4 +149,7 @@ * has_double, has_triple */ #define SYNAPTICS_PROP_CAPABILITIES "Synaptics Capabilities" +/* 32 bit, 2 values, vert, horiz */ +#define SYNAPTICS_PROP_RESOLUTION "Synaptics Pad Resolution" + #endif /* _SYNAPTICS_PROPERTIES_H_ */ diff --git a/man/synaptics.man b/man/synaptics.man index 8f7812c..342fb60 100644 --- a/man/synaptics.man +++ b/man/synaptics.man @@ -431,6 +431,21 @@ touching again and moving the finger on the touchpad. The gesture is enabled by default and can be disabled by setting the TapAndDragGesture option to false. Property: "Synaptics Gestures" . +.TP +.BI "Option \*qVertResolution\*q \*q" integer \*q +Resolution of X coordinates in units/millimeter. The value is used +together with HorizResolution to compensate unequal vertical and +horizontal sensitivity. Setting VertResolution and HorizResolution +equal values means no compensation. Property: "Synaptics Pad +Resolution" +. +.TP +.BI "Option \*qHorizResolution\*q \*q" integer \*q +Resolution of Y coordinates in units/millimeter. The value is used +together with VertResolution to compensate unequal vertical and +horizontal sensitivity. Setting VertResolution and HorizResolution +equal values means no compensation. Property: "Synaptics Pad +Resolution" .LP The LeftEdge, RightEdge, TopEdge and BottomEdge parameters are used to define the edge and corner areas of the touchpad. @@ -818,6 +833,10 @@ scrolling. 8 bit (BOOL), 5 values (read-only), has left button, has middle button, has right button, two-finger detection, three-finger detection. +.TP 7 +.BI "Synaptics Pad Resolution" +32 bit, 2 values, vertical, horizontal in units/millimeter. + .SH "NOTES" There is an example hal policy file in .I ${sourcecode}/fdi/11-x11-synaptics.fdi diff --git a/src/eventcomm.c b/src/eventcomm.c index 5ab34c0..ae853f2 100644 --- a/src/eventcomm.c +++ b/src/eventcomm.c @@ -171,7 +171,7 @@ static void event_query_axis_ranges(LocalDevicePtr local) { SynapticsPrivate *priv = (SynapticsPrivate *)local->private; - struct input_absinfo abs; + struct input_absinfo abs = {0}; unsigned long absbits[NBITS(ABS_MAX)] = {0}; unsigned long keybits[NBITS(KEY_MAX)] = {0}; char buf[256]; @@ -184,6 +184,9 @@ event_query_axis_ranges(LocalDevicePtr local) abs.minimum, abs.maximum); priv->minx = abs.minimum; priv->maxx = abs.maximum; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30) + priv->resx = abs.resolution; +#endif } else xf86Msg(X_ERROR, "%s: failed to query axis range (%s)\n", local->name, strerror(errno)); @@ -195,6 +198,9 @@ event_query_axis_ranges(LocalDevicePtr local) abs.minimum, abs.maximum); priv->miny = abs.minimum; priv->maxy = abs.maximum; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30) + priv->resy = abs.resolution; +#endif } else xf86Msg(X_ERROR, "%s: failed to query axis range (%s)\n", local->name, strerror(errno)); diff --git a/src/eventcomm.h b/src/eventcomm.h index a4a9a44..8fd7bcb 100644 --- a/src/eventcomm.h +++ b/src/eventcomm.h @@ -28,6 +28,7 @@ #define _EVENTCOMM_H_ #include +#include /* for auto-dev: */ #define DEV_INPUT_EVENT "/dev/input" diff --git a/src/properties.c b/src/properties.c index 70b59e0..80e62ab 100644 --- a/src/properties.c +++ b/src/properties.c @@ -82,6 +82,7 @@ Atom prop_pressuremotion_factor = 0; Atom prop_grab = 0; Atom prop_gestures = 0; Atom prop_capabilities = 0; +Atom prop_resolution = 0; static Atom InitAtom(DeviceIntPtr dev, char *name, int format, int nvalues, int *values) @@ -262,6 +263,11 @@ InitDeviceProperties(LocalDevicePtr local) values[3] = priv->has_double; values[4] = priv->has_triple; prop_capabilities = InitAtom(local->dev, SYNAPTICS_PROP_CAPABILITIES, 8, 5, values); + + values[0] = para->resolution_vert; + values[1] = para->resolution_horiz; + prop_resolution = InitAtom(local->dev, SYNAPTICS_PROP_RESOLUTION, 32, 2, values); + } int @@ -612,6 +618,19 @@ SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, { /* read-only */ return BadValue; + } else if (property == prop_resolution) + { + INT32 *dist; + if (prop->size != 2 || prop->format != 32 || prop->type != XA_INTEGER) + return BadMatch; + + dist = (INT32*)prop->data; + para->resolution_vert = dist[0]; + para->resolution_horiz = dist[1]; + + /* trigger recalculation of coefficients */ + priv->vert_coeff = 0; + priv->horiz_coeff = 0; } return Success; diff --git a/src/synaptics.c b/src/synaptics.c index e1e3646..d07ba59 100644 --- a/src/synaptics.c +++ b/src/synaptics.c @@ -129,6 +129,7 @@ static Bool DeviceOff(DeviceIntPtr); static Bool DeviceClose(DeviceIntPtr); static Bool QueryHardware(LocalDevicePtr); static void ReadDevDimensions(LocalDevicePtr); +static void ScaleCoordinates(SynapticsPrivate *priv, struct SynapticsHwState *hw); #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3 void InitDeviceProperties(LocalDevicePtr local); @@ -314,6 +315,8 @@ static void set_default_parameters(LocalDevicePtr local) int clickFinger1, clickFinger2, clickFinger3; Bool vertEdgeScroll, horizEdgeScroll; Bool vertTwoFingerScroll, horizTwoFingerScroll; + int horizResolution = 1; + int vertResolution = 1; /* read the parameters */ if (priv->synshm) @@ -436,6 +439,12 @@ static void set_default_parameters(LocalDevicePtr local) vertTwoFingerScroll = priv->has_double ? TRUE : FALSE; horizTwoFingerScroll = FALSE; + /* Use resolution reported by hardware if available */ + if ((priv->resx > 0) && (priv->resy > 0)) { + horizResolution = priv->resx; + vertResolution = priv->resy; + } + /* set the parameters */ pars->left_edge = xf86SetIntOption(opts, "LeftEdge", l); pars->right_edge = xf86SetIntOption(opts, "RightEdge", r); @@ -509,6 +518,8 @@ static void set_default_parameters(LocalDevicePtr local) pars->press_motion_max_factor = xf86SetRealOption(opts, "PressureMotionMaxFactor", 1.0); pars->grab_event_device = xf86SetBoolOption(opts, "GrabEventDevice", TRUE); pars->tap_and_drag_gesture = xf86SetBoolOption(opts, "TapAndDragGesture", TRUE); + pars->resolution_horiz = xf86SetIntOption(opts, "HorizResolution", horizResolution); + pars->resolution_vert = xf86SetIntOption(opts, "VertResolution", vertResolution); /* Warn about (and fix) incorrectly configured TopEdge/BottomEdge parameters */ if (pars->top_edge > pars->bottom_edge) { @@ -2137,6 +2148,8 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState *hw) if (timeleft > 0) delay = MIN(delay, timeleft); + ScaleCoordinates(priv, hw); + timeleft = ComputeDeltas(priv, hw, edge, &dx, &dy); delay = MIN(delay, timeleft); @@ -2322,3 +2335,32 @@ QueryHardware(LocalDevicePtr local) return TRUE; } +static void +ScaleCoordinates(SynapticsPrivate *priv, struct SynapticsHwState *hw) +{ + int minX = priv->synpara.left_edge; + int maxX = priv->synpara.right_edge; + int minY = priv->synpara.top_edge; + int maxY = priv->synpara.bottom_edge; + int vertRes = priv->synpara.resolution_vert; + int horizRes = priv->synpara.resolution_horiz; + int xCenter = (minX + maxX) / 2; + int yCenter = (minY + maxY) / 2; + + if ((priv->vert_coeff == 0) || (priv->horiz_coeff == 0)) { + if ((horizRes > vertRes) && (horizRes > 0)) { + priv->horiz_coeff = vertRes / (double)horizRes; + priv->vert_coeff = 1; + } else if ((horizRes < vertRes) && (vertRes > 0)) { + priv->horiz_coeff = 1; + priv->vert_coeff = horizRes / (double)vertRes; + } else { + priv->horiz_coeff = 1; + priv->vert_coeff = 1; + } + } + + hw->x = (hw->x - xCenter) * priv->horiz_coeff + xCenter; + hw->y = (hw->y - yCenter) * priv->vert_coeff + yCenter; +} + diff --git a/src/synapticsstr.h b/src/synapticsstr.h index d2ff57c..4370460 100644 --- a/src/synapticsstr.h +++ b/src/synapticsstr.h @@ -147,6 +147,8 @@ typedef struct _SynapticsParameters double press_motion_max_factor; /* factor applied on speed when finger pressure is at minimum */ Bool grab_event_device; /* grab event device for exclusive use? */ Bool tap_and_drag_gesture; /* Switches the tap-and-drag gesture on/off */ + int resolution_horiz; /* horizontal resolution of touchpad in units/mm */ + int resolution_vert; /* vertical resolution of touchpad in units/mm */ } SynapticsParameters; @@ -208,9 +210,12 @@ typedef struct _SynapticsPrivateRec palm/finger contact disappears */ int prev_z; /* previous z value, for palm detection */ int avg_width; /* weighted average of previous fingerWidth values */ + double horiz_coeff; /* normalization factor for x coordintes */ + double vert_coeff; /* normalization factor for y coordintes */ int minx, maxx, miny, maxy; /* min/max dimensions as detected */ int minp, maxp, minw, maxw; /* min/max pressure and finger width as detected */ + int resx, resy; /* resolution of coordinates as detected in units/mm */ Bool has_left; /* left button detected for this device */ Bool has_right; /* right button detected for this device */ Bool has_middle; /* middle button detected for this device */ diff --git a/tools/synclient.c b/tools/synclient.c index eed0c79..fce461c 100644 --- a/tools/synclient.c +++ b/tools/synclient.c @@ -139,6 +139,8 @@ static struct Parameter params[] = { {"PressureMotionMaxFactor", PT_DOUBLE, 0, 10.0,SYNAPTICS_PROP_PRESSURE_MOTION_FACTOR, 0 /*float*/, 1}, {"GrabEventDevice", PT_BOOL, 0, 1, SYNAPTICS_PROP_GRAB, 8, 0}, {"TapAndDragGesture", PT_BOOL, 0, 1, SYNAPTICS_PROP_GESTURES, 8, 0}, + {"VertResolution", PT_INT, 1, 255, SYNAPTICS_PROP_RESOLUTION, 32, 0}, + {"HorizResolution", PT_INT, 1, 255, SYNAPTICS_PROP_RESOLUTION, 32, 1}, { NULL, 0, 0, 0, 0 } };