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<[email protected]>
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
_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel