[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