[PATCH xf86-input-synaptics v3 08/10] Add soft button areas property

Chase Douglas chase.douglas at canonical.com
Thu Feb 23 17:49:40 PST 2012


On 02/23/2012 05:24 PM, Peter Hutterer wrote:
> On Thu, Feb 23, 2012 at 01:02:23PM -0800, Chase Douglas wrote:
>> Some clickpad devices have button areas painted on them. Set this
>> property to the area of the right and middle buttons to enable proper
>> click actions when clicking in the areas.
>>
>> Signed-off-by: Chase Douglas<chase.douglas at canonical.com>
>
> this needs synclient integration too, possible as follow-up. Likewise for
> any other option added.
>
>> ---
>>   include/synaptics-properties.h |    3 +
>>   man/synaptics.man              |   22 +++++
>>   src/properties.c               |   30 ++++++
>>   src/synaptics.c                |  193 ++++++++++++++++++++++++++++++++++++++++
>>   src/synapticsstr.h             |    8 ++
>>   src/synproto.h                 |    2 +
>>   6 files changed, 258 insertions(+), 0 deletions(-)
>>
>> diff --git a/include/synaptics-properties.h b/include/synaptics-properties.h
>> index 140f14b..8c20a0c 100644
>> --- a/include/synaptics-properties.h
>> +++ b/include/synaptics-properties.h
>> @@ -158,6 +158,9 @@
>>   /* 32 bit, 4 values, left, right, top, bottom */
>>   #define SYNAPTICS_PROP_AREA "Synaptics Area"
>>
>> +/* 32 bit, 4 values, left, right, top, buttom */
>> +#define SYNAPTICS_PROP_SOFTBUTTON_AREAS "Synaptics Soft Button Areas"
>> +
>>   /* 32 Bit Integer, 2 values, horizontal hysteresis, vertical hysteresis */
>>   #define SYNAPTICS_PROP_NOISE_CANCELLATION "Synaptics Noise Cancellation"
>>
>> diff --git a/man/synaptics.man b/man/synaptics.man
>> index 8edc2f0..f50b249 100644
>> --- a/man/synaptics.man
>> +++ b/man/synaptics.man
>> @@ -518,6 +518,20 @@ AreaBottomEdge option to any integer value other than zero. If supported by the
>>   server (version 1.9 and later), the edge may be specified in percent of
>>   the total height of the touchpad. Property: "Synaptics Area"
>>   .
>> +.TP
>> +.BI "Option \*qSoftButtonAreas\*q \*q" "RBL RBR RBT RBB MBL MBR MBT MBB" \*q
>> +Enable soft button click area support on ClickPad devices. The first four
>> +parameters define the area of the right button, and the second four parameters
>> +define the area of the middle button. The areas are defined by the left, right,
>> +top, and bottom edges as sequential values of the property. If any edge is set
>> +to 0, the edge is assumed to extend to infinity in the given direction.
>
> that is rather confusing wording. If RBR is 0, it extends to infinity? More
> that the button area does so.

I've now got:

If any edge is set to 0, the button is assumed to extend to infinity in 
the given direction.

> It also conflicts with the wording below
> according to this, if all values are 0 they should extend to infinity.

All values being 0 is a special case. I don't know how to write this 
without there being a conflict. The enabling of the feature is conflated 
with the settings of the feature, but I don't think this is a case where 
it makes sense to split it out.

>> +.
>> +When the user performs a click within the defined soft button areas, the right
>> +or middle click action is performed.
>> +.
>> +The use of soft button areas is disabled by setting all the values for the area
>> +to 0. Property: "Synaptics Soft Button Areas"
>> +.
>>
>>   .SH CONFIGURATION DETAILS
>>   .SS Area handling
>> @@ -927,6 +941,14 @@ default.
>>   32 bit, 4 values, left, right, top, bottom. 0 disables an element.
>>
>>   .TP 7
>> +.BI "Synaptics Soft Button Areas"
>> +The Right and middle soft button areas are used to support right and middle
>> +click actions on a ClickPad device. Providing 0 for all values of a given button
>> +disables the button area.
>
> this should be up there too.

It is. It looks like documentation for the X device properties doesn't 
really contain info about the options, so I thought about just leaving 
the first sentence. However, knowing how to disable it seemed important 
enough to state it here again.

>> +
>> +32 bit, 8 values, RBL, RBR, RBT, RBB, MBL, MBR, MBT, MBB.
>> +
>> +.TP 7
>>   .BI "Synaptics Capabilities"
>>   This read-only property expresses the physical capability of the touchpad,
>>   most notably whether the touchpad hardware supports multi-finger tapping and
>> diff --git a/src/properties.c b/src/properties.c
>> index 38f21b2..3828229 100644
>> --- a/src/properties.c
>> +++ b/src/properties.c
>> @@ -92,6 +92,7 @@ Atom prop_gestures              = 0;
>>   Atom prop_capabilities          = 0;
>>   Atom prop_resolution            = 0;
>>   Atom prop_area                  = 0;
>> +Atom prop_softbutton_areas      = 0;
>>   Atom prop_noise_cancellation    = 0;
>>   Atom prop_product_id            = 0;
>>   Atom prop_device_node           = 0;
>> @@ -300,6 +301,16 @@ InitDeviceProperties(InputInfoPtr pInfo)
>>       values[3] = para->area_bottom_edge;
>>       prop_area = InitAtom(pInfo->dev, SYNAPTICS_PROP_AREA, 32, 4, values);
>>
>> +    values[0] = para->softbutton_right_left_edge;
>> +    values[1] = para->softbutton_right_right_edge;
>> +    values[2] = para->softbutton_right_top_edge;
>> +    values[3] = para->softbutton_right_bottom_edge;
>> +    values[4] = para->softbutton_middle_left_edge;
>> +    values[5] = para->softbutton_middle_right_edge;
>> +    values[6] = para->softbutton_middle_top_edge;
>> +    values[7] = para->softbutton_middle_bottom_edge;
>> +    prop_softbutton_areas = InitAtom(pInfo->dev, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 8, values);
>> +
>>       values[0] = para->hyst_x;
>>       values[1] = para->hyst_y;
>>       prop_noise_cancellation = InitAtom(pInfo->dev,
>> @@ -711,6 +722,25 @@ SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
>>           para->area_right_edge  = area[1];
>>           para->area_top_edge    = area[2];
>>           para->area_bottom_edge = area[3];
>> +    } else if (property == prop_softbutton_areas)
>> +    {
>> +        INT32 *areas;
>> +
>> +        if (prop->size != 8 || prop->format != 32 || prop->type != XA_INTEGER)
>> +            return BadMatch;
>> +
>> +        areas = (INT32*)prop->data;
>> +        if (!SynapticsIsSoftButtonAreasValid(areas))
>> +            return BadValue;
>> +
>> +        para->softbutton_right_left_edge    = areas[0];
>> +        para->softbutton_right_right_edge   = areas[1];
>> +        para->softbutton_right_top_edge     = areas[2];
>> +        para->softbutton_right_bottom_edge  = areas[3];
>> +        para->softbutton_middle_left_edge   = areas[4];
>> +        para->softbutton_middle_right_edge  = areas[5];
>> +        para->softbutton_middle_top_edge    = areas[6];
>> +        para->softbutton_middle_bottom_edge = areas[7];
>>       } else if (property == prop_noise_cancellation) {
>>           INT32 *hyst;
>>           if (prop->size != 2 || prop->format != 32 || prop->type != XA_INTEGER)
>> diff --git a/src/synaptics.c b/src/synaptics.c
>> index 05ea6b9..26ac5ef 100644
>> --- a/src/synaptics.c
>> +++ b/src/synaptics.c
>> @@ -410,6 +410,127 @@ static int set_percent_option(pointer options, const char* optname,
>>       return result;
>>   }
>>
>> +Bool SynapticsIsSoftButtonAreasValid(int *values)
>> +{
>> +    Bool right_disabled = FALSE;
>> +    Bool middle_disabled = FALSE;
>> +
>> +    /* Check right button area */
>> +    if ((((values[0] != 0)&&  (values[1] != 0))&&  (values[0]>  values[1])) ||
>> +        (((values[2] != 0)&&  (values[3] != 0))&&  (values[2]>  values[3])))
>> +        return FALSE;
>> +
>> +    /* Check middle button area */
>> +    if ((((values[4] != 0)&&  (values[5] != 0))&&  (values[4]>  values[5])) ||
>> +        (((values[6] != 0)&&  (values[7] != 0))&&  (values[6]>  values[7])))
>> +        return FALSE;
>> +
>> +    if (values[0] == 0&&  values[1] == 0&&  values[2] == 0&&  values[3] == 0)
>> +        right_disabled = TRUE;
>> +
>> +    if (values[4] == 0&&  values[5] == 0&&  values[6] == 0&&  values[7] == 0)
>> +        middle_disabled = TRUE;
>> +
>> +    /* Check for overlapping button areas */
>> +    if (!right_disabled&&  !middle_disabled)
>> +    {
>> +        int right_left = values[0] ? values[0] : -INT_MAX;
>
> shouldn't this be INT_MIN?

Yeah, brain fart (and rush to get it in before Precise beta freeze)

>> +        int right_right = values[1] ? values[1] : INT_MAX;
>> +        int right_top = values[2] ? values[2] : -INT_MAX;
>> +        int right_bottom = values[3] ? values[3] : INT_MAX;
>> +        int middle_left = values[4] ? values[4] : -INT_MAX;
>> +        int middle_right = values[5] ? values[5] : INT_MAX;
>> +        int middle_top = values[6] ? values[6] : -INT_MAX;
>> +        int middle_bottom = values[7] ? values[7] : INT_MAX;
>> +
>> +        /* If areas overlap in the Y axis */
>> +        if ((right_bottom<= middle_bottom&&  right_bottom>= middle_top) ||
>> +            (right_top<= middle_bottom&&  right_top>= middle_top))
>> +        {
>> +            /* Check for identical right and left edges */
>> +            if (right_left == middle_left || right_right == middle_right)
>> +                return FALSE;
>> +
>> +            /* Check for overlapping left edges */
>> +            if ((right_left<  middle_left&&  right_right>= middle_left) ||
>> +                (middle_left<  right_left&&  middle_right>= right_left))
>> +                return FALSE;
>> +
>> +            /* Check for overlapping right edges */
>> +            if ((right_right>  middle_right&&  right_left<= middle_right) ||
>> +                (middle_right>  right_right&&  middle_left<= right_right))
>> +                return FALSE;
>> +        }
>> +
>> +        /* If areas overlap in the X axis */
>> +        if ((right_left>= middle_left&&  right_left<= middle_right) ||
>> +            (right_right>= middle_left&&  right_right<= middle_right))
>> +        {
>> +            /* Check for overlapping top edges */
>> +            if ((right_top<  middle_top&&  right_bottom>= middle_top) ||
>> +                (middle_top<  right_top&&  middle_bottom>= right_top))
>> +                return FALSE;
>> +
>> +            /* Check for overlapping bottom edges */
>> +            if ((right_bottom>  middle_bottom&&  right_top<= middle_bottom) ||
>> +                (middle_bottom>  right_bottom&&  middle_top<= right_bottom))
>> +                return FALSE;
>> +        }
>> +    }
>> +
>> +    return TRUE;
>> +}
>> +
>> +static void set_softbutton_areas_option(InputInfoPtr pInfo)
>> +{
>> +    SynapticsPrivate *priv = pInfo->private;
>> +    SynapticsParameters *pars =&priv->synpara;
>> +    int values[8];
>> +    char *option_string;
>> +    char *next_num;
>> +    char *end_str;
>> +    int i;
>> +
>> +    option_string = xf86CheckStrOption(pInfo->options, "SoftButtonAreas", NULL);
>> +    if (!option_string)
>> +        return;
>> +
>> +    next_num = option_string;
>> +
>> +    for (i = 0; i<  8&&  *next_num != '\0'; i++)
>> +    {
>> +        long int value = strtol(next_num,&end_str, 0);
>> +        if (value>  INT_MAX || value<  -INT_MAX)
>> +            goto fail;
>> +
>> +        values[i] = value;
>> +
>> +        if (next_num != end_str)
>> +            next_num = end_str;
>> +        else
>> +            goto fail;
>> +    }
>> +
>> +    if (i<  8 || *next_num != '\0' || !SynapticsIsSoftButtonAreasValid(values))
>> +        goto fail;
>> +
>> +    pars->softbutton_right_left_edge = values[0];
>> +    pars->softbutton_right_right_edge = values[1];
>> +    pars->softbutton_right_top_edge = values[2];
>> +    pars->softbutton_right_bottom_edge = values[3];
>> +    pars->softbutton_middle_left_edge = values[4];
>> +    pars->softbutton_middle_right_edge = values[5];
>> +    pars->softbutton_middle_top_edge = values[6];
>> +    pars->softbutton_middle_bottom_edge = values[7];
>> +
>> +    return;
>> +
>> +fail:
>> +    xf86IDrvMsg(pInfo, X_WARNING, "invalid SoftButtonAreas value '%s'\n",
>> +                option_string);
>
> X_ERROR, and it should state what it does here (i.e. "ignoring area")

Ok

>> +}
>> +
>> +
>>   static void set_default_parameters(InputInfoPtr pInfo)
>>   {
>>       SynapticsPrivate *priv = pInfo->private; /* read-only */
>> @@ -602,6 +723,8 @@ static void set_default_parameters(InputInfoPtr pInfo)
>>   	pars->bottom_edge = tmp;
>>   	xf86IDrvMsg(pInfo, X_WARNING, "TopEdge is bigger than BottomEdge. Fixing.\n");
>>       }
>> +
>> +    set_softbutton_areas_option(pInfo);
>>   }
>>
>>   #if GET_ABI_MAJOR(ABI_XINPUT_VERSION)>= 14
>> @@ -1355,6 +1478,60 @@ is_inside_active_area(SynapticsPrivate *priv, int x, int y)
>>       return inside_area;
>>   }
>>
>> +static Bool
>> +is_inside_rightbutton_area(SynapticsParameters *para, int x, int y)
>> +{
>> +    Bool inside_area = TRUE;
>> +
>> +    if (para->softbutton_right_left_edge == 0&&
>> +        para->softbutton_right_right_edge == 0&&
>> +        para->softbutton_right_top_edge == 0&&
>> +        para->softbutton_right_bottom_edge == 0)
>> +        return FALSE;
>> +
>> +    if (para->softbutton_right_left_edge&&
>> +        x<  para->softbutton_right_left_edge)
>> +	inside_area = FALSE;
>> +    else if (para->softbutton_right_right_edge&&
>> +             x>  para->softbutton_right_right_edge)
>> +	inside_area = FALSE;
>> +    else if (para->softbutton_right_top_edge&&
>> +             y<  para->softbutton_right_top_edge)
>> +	inside_area = FALSE;
>> +    else if (para->softbutton_right_bottom_edge&&
>> +             y>  para->softbutton_right_bottom_edge)
>> +	inside_area = FALSE;
>> +
>> +    return inside_area;
>> +}
>> +
>> +static Bool
>> +is_inside_middlebutton_area(SynapticsParameters *para, int x, int y)
>> +{
>> +    Bool inside_area = TRUE;
>> +
>> +    if (para->softbutton_middle_left_edge == 0&&
>> +        para->softbutton_middle_right_edge == 0&&
>> +        para->softbutton_middle_top_edge == 0&&
>> +        para->softbutton_middle_bottom_edge == 0)
>> +        return FALSE;
>> +
>> +    if (para->softbutton_middle_left_edge&&
>> +        x<  para->softbutton_middle_left_edge)
>> +	inside_area = FALSE;
>> +    else if (para->softbutton_middle_right_edge&&
>> +             x>  para->softbutton_middle_right_edge)
>> +	inside_area = FALSE;
>> +    else if (para->softbutton_middle_top_edge&&
>> +             y<  para->softbutton_middle_top_edge)
>> +	inside_area = FALSE;
>> +    else if (para->softbutton_middle_bottom_edge&&
>> +             y>  para->softbutton_middle_bottom_edge)
>> +	inside_area = FALSE;
>> +
>> +    return inside_area;
>> +}
>> +
>>   static CARD32
>>   timerFunc(OsTimerPtr timer, CARD32 now, pointer arg)
>>   {
>> @@ -2498,6 +2675,22 @@ update_hw_button_state(const InputInfoPtr pInfo, struct SynapticsHwState *hw,
>>       /* 3rd button emulation */
>>       hw->middle |= HandleMidButtonEmulation(priv, hw, now, delay);
>>
>> +    /* If this is a clickpad and the user clicks in a soft button area, press
>> +     * the soft button instead. */
>> +    if (para->clickpad&&  hw->left&&  !hw->right&&  !hw->middle)
>> +    {
>> +        if (is_inside_rightbutton_area(para, hw->x, hw->y))
>> +        {
>> +            hw->left = 0;
>> +            hw->right = 1;
>> +        }
>> +        else if (is_inside_middlebutton_area(para, hw->x, hw->y))
>> +        {
>> +            hw->left = 0;
>> +            hw->middle = 1;
>> +        }
>> +    }
>> +
>>       /* Fingers emulate other buttons */
>>       if(!para->clickpad&&  hw->left&&  hw->numFingers>= 1){
>>           handle_clickfinger(para, hw);
>> diff --git a/src/synapticsstr.h b/src/synapticsstr.h
>> index 944fd6b..baee4d9 100644
>> --- a/src/synapticsstr.h
>> +++ b/src/synapticsstr.h
>> @@ -180,6 +180,14 @@ typedef struct _SynapticsParameters
>>       unsigned int resolution_horiz;          /* horizontal resolution of touchpad in units/mm */
>>       unsigned int resolution_vert;           /* vertical resolution of touchpad in units/mm */
>>       int area_left_edge, area_right_edge, area_top_edge, area_bottom_edge; /* area coordinates absolute */
>> +    int softbutton_right_left_edge;
>> +    int softbutton_right_right_edge;
>> +    int softbutton_right_top_edge;
>> +    int softbutton_right_bottom_edge;
>> +    int softbutton_middle_left_edge;
>> +    int softbutton_middle_right_edge;
>> +    int softbutton_middle_top_edge;
>> +    int softbutton_middle_bottom_edge;       /* soft button area coordinates absolute */
>
> yikes. can we use an array please?

Yeah.

-- Chase


More information about the xorg-devel mailing list