From 5534b0d79949f02ca1e2151cd265c74dff811240 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 30 Jun 2009 10:48:33 +1000 Subject: [PATCH] Auto-adjust edges if values fall outside queried min/max ranges. (#21001) The kernel provides min/max for x/y values but still allows devices to send coordinates outside this range. If the edges are autodetected, re-adjust the edge settings to fit within the new effective min/max range. If the edges were configured by the user, don't re-adjust. This obsoletes the SpecialScrollAreaRight option as it provides the same functionality, without the side-effects triggering 21001. X.Org Bug 21001 Signed-off-by: Peter Hutterer --- man/synaptics.man | 17 +++++++----- src/synaptics.c | 69 ++++++++++++++++++++++++++++++++++----------------- src/synapticsstr.h | 1 + 3 files changed, 57 insertions(+), 30 deletions(-) diff --git a/man/synaptics.man b/man/synaptics.man index 8f7812c..5b98082 100644 --- a/man/synaptics.man +++ b/man/synaptics.man @@ -99,9 +99,7 @@ option is not needed with synaptics 1.0 or later. See section X coordinate for left edge. Property: "Synaptics Edges" .TP 7 .BI "Option \*qRightEdge\*q \*q" integer \*q -X coordinate for right edge. If this option is set, -.BI SpecialScrollAreaRight -is ignored. Property: "Synaptics Edges" +X coordinate for right edge. Property: "Synaptics Edges" .TP 7 .BI "Option \*qTopEdge\*q \*q" integer \*q Y coordinate for top edge. Property: "Synaptics Edges" @@ -109,10 +107,6 @@ Y coordinate for top edge. Property: "Synaptics Edges" .BI "Option \*qBottomEdge\*q \*q" integer \*q Y coordinate for bottom edge. Property: "Synaptics Edges" .TP 7 -.BI "Option \*qSpecialScrollAreaRight\*q \*q" boolean \*q -Some touchpads have a scroll region on the right edge. Disable this option if -you have one but don't want use it as scroll wheel region. -.TP 7 .BI "Option \*qFingerLow\*q \*q" integer \*q When finger pressure drops below this value, the driver counts it as a release. Property: "Synaptics Finger" @@ -842,6 +836,11 @@ Tapping is disabled by default for touchpads with one or more physical buttons. To enable it you need to map tap actions to buttons. See the "TapButton1", "TapButton2" and "TapButton3" options. .LP +Some devices report min/max values but provide values outside this range. +In this case, the driver auto-adjusts the edge values. Acceleration and +speed values are not affected. User-specified edges are not +auto-adjusted. +.LP Button mapping for physical buttons is handled in the server. If the device is switched to left-handed (an in-server mapping of physical buttons 1, 2, 3 to the logical buttons 3, 2, 1, respectively), both physical @@ -854,6 +853,10 @@ The following options are no longer part of the driver configuration: .BI "Option \*qRepeater\*q \*q" string \*q .TP .BI "Option \*qHistorySize\*q \*q" integer \*q +.TP 7 +.BI "Option \*qSpecialScrollAreaRight\*q \*q" boolean \*q +Some touchpads have a scroll region on the right edge. Disable this option if +you have one but don't want use it as scroll wheel region. .SH "AUTHORS" .LP diff --git a/src/synaptics.c b/src/synaptics.c index 6eeb77f..1de6eb3 100644 --- a/src/synaptics.c +++ b/src/synaptics.c @@ -439,6 +439,10 @@ static void set_default_parameters(LocalDevicePtr local) horizTwoFingerScroll = FALSE; /* set the parameters */ + pars->edges_forced[LEFT_EDGE] = xf86CheckIfOptionUsedByName(opts, "LeftEdge"); + pars->edges_forced[RIGHT_EDGE] = xf86CheckIfOptionUsedByName(opts, "RightEdge"); + pars->edges_forced[TOP_EDGE] = xf86CheckIfOptionUsedByName(opts, "TopEdge"); + pars->edges_forced[BOTTOM_EDGE] = xf86CheckIfOptionUsedByName(opts, "BottomEdge"); pars->edges[LEFT_EDGE] = xf86SetIntOption(opts, "LeftEdge", l); pars->edges[RIGHT_EDGE] = xf86SetIntOption(opts, "RightEdge", r); pars->edges[TOP_EDGE] = xf86SetIntOption(opts, "TopEdge", t); @@ -458,11 +462,6 @@ static void set_default_parameters(LocalDevicePtr local) pars->scroll_dist_vert = xf86SetIntOption(opts, "VertScrollDelta", horizScrollDelta); pars->scroll_dist_horiz = xf86SetIntOption(opts, "HorizScrollDelta", vertScrollDelta); pars->scroll_edge_vert = xf86SetBoolOption(opts, "VertEdgeScroll", vertEdgeScroll); - if (xf86CheckIfOptionUsedByName(opts, "RightEdge")) { - pars->special_scroll_area_right = FALSE; - } else { - pars->special_scroll_area_right = xf86SetBoolOption(opts, "SpecialScrollAreaRight", TRUE); - } pars->scroll_edge_horiz = xf86SetBoolOption(opts, "HorizEdgeScroll", horizEdgeScroll); pars->scroll_edge_corner = xf86SetBoolOption(opts, "CornerCoasting", FALSE); pars->scroll_twofinger_vert = xf86SetBoolOption(opts, "VertTwoFingerScroll", vertTwoFingerScroll); @@ -607,8 +606,6 @@ SynapticsPreInit(InputDriverPtr drv, IDevPtr dev, int flags) set_default_parameters(local); - priv->largest_valid_x = MIN(priv->synpara.edges[RIGHT_EDGE], XMAX_NOMINAL); - if (!alloc_param_data(local)) goto SetupProc_fail; @@ -2108,22 +2105,48 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState *hw) hw->multi[2] = hw->multi[3] = FALSE; } - /* - * Some touchpads have a scroll wheel region where a very large X - * coordinate is reported. In this case for eliminate discontinuity, - * we adjust X and simulate new zone which adjacent to right edge. - */ - if (hw->x <= XMAX_VALID) { - if (priv->largest_valid_x < hw->x) - priv->largest_valid_x = hw->x; - } else { - hw->x = priv->largest_valid_x + 1; - /* - * If user didn't set right_edge manualy, auto-adjust to bounds of - * hardware scroll area. - */ - if (para->special_scroll_area_right) - priv->synpara.edges[RIGHT_EDGE] = priv->largest_valid_x; + /* The kernel doesn't clip into min/max, so auto-adjust the edges if we + * go beyond min/max */ + if (hw->x > priv->maxx || hw->x < priv->minx || + hw->y > priv->maxy || hw->y < priv->miny) + { + int l, r, t, b; + Bool changed = FALSE; + + if (hw->x > priv->maxx && !para->edges_forced[RIGHT_EDGE]) + { + priv->maxx = hw->x; + changed = TRUE; + } else if (hw->x < priv->minx && !para->edges_forced[LEFT_EDGE]) + { + priv->minx = hw->x; + changed = TRUE; + } + + if (hw->y >= priv->maxy && !para->edges_forced[BOTTOM_EDGE]) + { + priv->maxy = hw->y; + changed = TRUE; + } else if (hw->y >= priv->miny && !para->edges_forced[TOP_EDGE]) + { + priv->miny = hw->y; + changed = TRUE; + } + + if (changed) + { + calculate_edge_widths(priv, &l, &r, &t, &b); + if (!para->edges_forced[LEFT_EDGE]) + para->edges[LEFT_EDGE] = l; + if (!para->edges_forced[RIGHT_EDGE]) + para->edges[RIGHT_EDGE] = r; + if (!para->edges_forced[TOP_EDGE]) + para->edges[TOP_EDGE] = t; + if (!para->edges_forced[BOTTOM_EDGE]) + para->edges[BOTTOM_EDGE] = b; + + /* FIXME: property notify */ + } } edge = edge_detection(priv, hw->x, hw->y); diff --git a/src/synapticsstr.h b/src/synapticsstr.h index aed5689..7da6c5e 100644 --- a/src/synapticsstr.h +++ b/src/synapticsstr.h @@ -102,6 +102,7 @@ typedef struct _SynapticsParameters { /* Parameter data */ int edges[RIGHT_EDGE]; /* edge coordinates absolute */ + Bool edges_forced[RIGHT_EDGE]; /* edges set manually? */ int finger_low, finger_high, finger_press; /* finger detection values in Z-values */ int tap_time; int tap_move; /* max. tapping time and movement in packets and coord. */ -- 1.6.3.rc1.2.g0164.dirty From 2d1ac5e84bcebd68f3e66bc2e106c9b59401e9c3 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 2 Jul 2009 15:35:38 +1000 Subject: [PATCH] Implement property notifies for changed edges. To be squashed with previous patch. When the edges change the property needs to be updated accordingly. This can't be done immediately as changing properties requires mallocs and HandleState is called during the signal handler. Instead, set a timer to be called when the server isn't busy and update the property then. The delay between setting the timer and sending the property notify event also reduces the number of events sent, the property event includes the latest state only. Signed-off-by: Peter Hutterer --- src/properties.c | 17 +++++++++++++++++ src/synaptics.c | 43 ++++++++++++++++++++++++++++++++++++++++++- src/synapticsstr.h | 4 +++- 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/properties.c b/src/properties.c index c571c34..4a2daf7 100644 --- a/src/properties.c +++ b/src/properties.c @@ -617,5 +617,22 @@ SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, return Success; } +void +SetEdgeProperty(LocalDevicePtr local) +{ + SynapticsPrivate *priv = (SynapticsPrivate*) (local->private); + SynapticsParameters *para = &priv->synpara; + uint32_t values[4]; + + values[0] = para->edges[LEFT_EDGE]; + values[1] = para->edges[RIGHT_EDGE]; + values[2] = para->edges[TOP_EDGE]; + values[3] = para->edges[BOTTOM_EDGE]; + + XIChangeDeviceProperty(local->dev, prop_edges, XA_INTEGER, 32, + PropModeReplace, 4, values, FALSE); +} + + #endif diff --git a/src/synaptics.c b/src/synaptics.c index 1de6eb3..a40d160 100644 --- a/src/synaptics.c +++ b/src/synaptics.c @@ -96,6 +96,9 @@ #define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ #endif +#define PROPERTY_TIMER_SET 0x1 +#define PROPERTY_NOTIFY_NEEDED 0x2 + #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 1 #define DBG(a,b) #endif @@ -123,6 +126,7 @@ static void ReadDevDimensions(LocalDevicePtr); void InitDeviceProperties(LocalDevicePtr local); int SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, BOOL checkonly); +int SetEdgeProperty(LocalDevicePtr local); #endif InputDriverRec SYNAPTICS = { @@ -542,6 +546,12 @@ SynapticsPreInit(InputDriverPtr drv, IDevPtr dev, int flags) return NULL; } + priv->property_notify_timer = TimerSet(NULL, 0, 0, NULL, NULL); + if (!priv->property_notify_timer) { + xfree(priv); + return NULL; + } + /* Allocate a new InputInfoRec and add it to the head xf86InputDevs. */ local = xf86AllocateInput(drv, 0); if (!local) { @@ -766,7 +776,9 @@ DeviceOff(DeviceIntPtr dev) if (local->fd != -1) { TimerFree(priv->timer); + TimerFree(priv->property_notify_timer); priv->timer = NULL; + priv->property_notify_timer = NULL; xf86RemoveEnabledDevice(local); if (priv->proto_ops->DeviceOffHook) priv->proto_ops->DeviceOffHook(local); @@ -1025,6 +1037,27 @@ edge_detection(SynapticsPrivate *priv, int x, int y) return edge; } +#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3 +static CARD32 +propertyTimerFunc(OsTimerPtr timer, CARD32 now, pointer arg) +{ + LocalDevicePtr local = (LocalDevicePtr) (arg); + SynapticsPrivate *priv = (SynapticsPrivate *) (local->private); + int sigstate; + + if (!priv->had_edge_change) + return 0; + + sigstate = xf86BlockSIGIO(); + + SetEdgeProperty(local); + + priv->had_edge_change = 0; + xf86UnblockSIGIO(sigstate); + return 0; +} +#endif + static CARD32 timerFunc(OsTimerPtr timer, CARD32 now, pointer arg) { @@ -1097,6 +1130,14 @@ ReadInput(LocalDevicePtr local) if (newDelay) priv->timer = TimerSet(priv->timer, 0, delay, timerFunc, local); + +#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3 + if (!(priv->had_edge_change & PROPERTY_TIMER_SET)) { + priv->property_notify_timer = + TimerSet(priv->property_notify_timer, 0, 100, propertyTimerFunc, local); + priv->had_edge_change |= PROPERTY_TIMER_SET; + } +#endif } static int @@ -2145,7 +2186,7 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState *hw) if (!para->edges_forced[BOTTOM_EDGE]) para->edges[BOTTOM_EDGE] = b; - /* FIXME: property notify */ + priv->had_edge_change |= PROPERTY_NOTIFY_NEEDED; } } diff --git a/src/synapticsstr.h b/src/synapticsstr.h index 7da6c5e..9668736 100644 --- a/src/synapticsstr.h +++ b/src/synapticsstr.h @@ -182,7 +182,6 @@ typedef struct _SynapticsPrivateRec SynapticsMoveHistRec move_hist[SYNAPTICS_MOVE_HISTORY]; /* movement history */ int hist_index; /* Last added entry in move_hist[] */ - int largest_valid_x; /* Largest valid X coordinate seen so far */ int scroll_y; /* last y-scroll position */ int scroll_x; /* last x-scroll position */ double scroll_a; /* last angle-scroll position */ @@ -232,6 +231,9 @@ typedef struct _SynapticsPrivateRec Bool has_pressure; /* device reports pressure */ enum TouchpadModel model; /* The detected model */ + + int had_edge_change; /* Non-zero if the edges have changed */ + OsTimerPtr property_notify_timer; /* For sending off property notify events */ } SynapticsPrivate; #endif /* _SYNAPTICSSTR_H_ */ -- 1.6.3.rc1.2.g0164.dirty