diff options
author | Peter Osterlund <petero2@telia.com> | 2003-09-25 01:37:13 +0200 |
---|---|---|
committer | Peter Osterlund <petero2@telia.com> | 2006-04-09 04:01:12 +0200 |
commit | a37a1239a79d0147dbd76e7346108d4b7a836864 (patch) | |
tree | 507aa7a47fa006d5ec858eed039fe98497bdb6c8 | |
parent | fe3d1e6d2bae13264eb85d2466d1e8c78686d993 (diff) |
Added support for the new 2.6 kernel events ABS_TOOL_WIDTH,
BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP and BTN_TOOL_TRIPLETAP. Note that
this swaps the direction of the Y axis internally to match X and the
linux input subsystem. Because of this, the TopEdge and BottomEdge
parameters must be modified in the config file. There is some backwards
compatibility code for old 2.5/2.6 kernels that will probably be
deleted later.
-rw-r--r-- | INSTALL | 4 | ||||
-rw-r--r-- | linux_input.h | 4 | ||||
-rw-r--r-- | synaptics.c | 150 | ||||
-rw-r--r-- | synaptics.h | 14 | ||||
-rw-r--r-- | synclient.c | 22 |
5 files changed, 141 insertions, 53 deletions
@@ -31,8 +31,8 @@ Section "InputDevice" Option "Protocol" "auto-dev" Option "LeftEdge" "1900" Option "RightEdge" "5400" - Option "TopEdge" "3900" - Option "BottomEdge" "1800" + Option "TopEdge" "1900" + Option "BottomEdge" "4000" Option "FingerLow" "25" Option "FingerHigh" "30" Option "MaxTapTime" "180" diff --git a/linux_input.h b/linux_input.h index 39762d5..9e8c487 100644 --- a/linux_input.h +++ b/linux_input.h @@ -47,10 +47,14 @@ struct input_id { #define BTN_5 0x105 #define BTN_6 0x106 #define BTN_7 0x107 +#define BTN_TOOL_FINGER 0x145 +#define BTN_TOOL_DOUBLETAP 0x14d +#define BTN_TOOL_TRIPLETAP 0x14e #define ABS_X 0x00 #define ABS_Y 0x01 #define ABS_PRESSURE 0x18 +#define ABS_TOOL_WIDTH 0x1c #define MSC_GESTURE 0x02 diff --git a/synaptics.c b/synaptics.c index feaf2d4..522633c 100644 --- a/synaptics.c +++ b/synaptics.c @@ -75,6 +75,16 @@ * Local Variables and Types ****************************************************************************/ +/* + * The x/y limits are taken from the Synaptics TouchPad interfacing Guide, + * section 2.3.2, which says that they should be valid regardless of the + * actual size of the sensor. + */ +#define XMIN_NOMINAL 1472 +#define XMAX_NOMINAL 5472 +#define YMIN_NOMINAL 1408 +#define YMAX_NOMINAL 4448 + #define MAX_UNSYNC_PACKETS 10 /* i.e. 10 to 60 bytes */ typedef enum { @@ -541,9 +551,9 @@ edge_detection(SynapticsPrivatePtr priv, int x, int y) else if (x < priv->synpara->left_edge) edge |= LEFT_EDGE; - if (y > priv->synpara->top_edge) + if (y < priv->synpara->top_edge) edge |= TOP_EDGE; - else if (y < priv->synpara->bottom_edge) + else if (y > priv->synpara->bottom_edge) edge |= BOTTOM_EDGE; return edge; @@ -700,30 +710,30 @@ SynapticsDetectFinger(SynapticsPrivatePtr priv, struct SynapticsHwState* hw) /* palm detection */ if (finger) { - if ((hw->z > 200) && (hw->w > 10)) + if ((hw->z > 200) && (hw->fingerWidth > 10)) priv->palm = TRUE; } else { priv->palm = FALSE; } if (hw->x == 0) - priv->avg_w = 0; + priv->avg_width = 0; else - priv->avg_w += (hw->w - priv->avg_w + 1) / 2; + priv->avg_width += (hw->fingerWidth - priv->avg_width + 1) / 2; if (finger && !priv->finger_flag) { - int safe_w = MAX(hw->w, priv->avg_w); - if (hw->w < 2) - finger = TRUE; /* more than one finger -> not a palm */ - else if ((safe_w < 6) && (priv->prev_z < para->finger_high)) - finger = TRUE; /* thin finger, distinct touch -> not a palm */ - else if ((safe_w < 7) && (priv->prev_z < para->finger_high / 2)) - finger = TRUE; /* thin finger, distinct touch -> not a palm */ - else if (hw->z > priv->prev_z + 1) /* z not stable, may be a palm */ + int safe_width = MAX(hw->fingerWidth, priv->avg_width); + if (hw->twoFingers || hw->threeFingers) + finger = TRUE; /* more than one finger -> not a palm */ + else if ((safe_width < 6) && (priv->prev_z < para->finger_high)) + finger = TRUE; /* thin finger, distinct touch -> not a palm */ + else if ((safe_width < 7) && (priv->prev_z < para->finger_high / 2)) + finger = TRUE; /* thin finger, distinct touch -> not a palm */ + else if (hw->z > priv->prev_z + 1) /* z not stable, may be a palm */ finger = FALSE; - else if (hw->z < priv->prev_z - 5) /* z not stable, may be a palm */ + else if (hw->z < priv->prev_z - 5) /* z not stable, may be a palm */ finger = FALSE; else if (hw->z > 200) /* z too large -> probably palm */ finger = FALSE; - else if (hw->w > 10) /* w too large -> probably palm */ + else if (hw->fingerWidth > 10) /* finger width too large -> probably palm */ finger = FALSE; } priv->prev_z = hw->z; @@ -765,7 +775,15 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState* hw) para->x = hw->x; para->y = hw->y; para->z = hw->z; - para->w = hw->w; + if (hw->oneFinger) + para->numFingers = 1; + else if (hw->twoFingers) + para->numFingers = 2; + else if (hw->threeFingers) + para->numFingers = 3; + else + para->numFingers = 0; + para->fingerWidth = hw->fingerWidth; para->left = hw->left; para->right = hw->right; para->up = hw->up; @@ -875,9 +893,9 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState* hw) if (finger && /* finger is on the surface */ (timeleft > 0)) /* tap time is not succeeded */ { /* count fingers when reported */ - if ((hw->w == 0) && (priv->finger_count == 0)) + if (hw->twoFingers && (priv->finger_count == 0)) priv->finger_count = 2; - if (hw->w == 1) + if (hw->threeFingers) priv->finger_count = 3; } else @@ -943,13 +961,13 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState* hw) scroll_up = 0; scroll_down = 0; if (priv->vert_scroll_on) { - /* + = up, - = down */ + /* + = down, - = up */ while (hw->y - priv->scroll_y > para->scroll_dist_vert) { - scroll_up++; + scroll_down++; priv->scroll_y += para->scroll_dist_vert; } while (hw->y - priv->scroll_y < -para->scroll_dist_vert) { - scroll_down++; + scroll_up++; priv->scroll_y -= para->scroll_dist_vert; } } @@ -972,12 +990,8 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState* hw) !priv->finger_count && !priv->palm) { delay = MIN(delay, 13); if (priv->count_packet_finger > 3) { /* min. 3 packets */ - dy = (1 * - (((MOVE_HIST(1).y + MOVE_HIST(2).y) / 2) - - ((hw->y + MOVE_HIST(1).y) / 2))); - dx = (-1 * - (((MOVE_HIST(1).x + MOVE_HIST(2).x) / 2) - - ((hw->x + MOVE_HIST(1).x) / 2))); + dx = (hw->x - MOVE_HIST(2).x) / 2; + dy = (hw->y - MOVE_HIST(2).y) / 2; if (priv->drag) { if (edge & RIGHT_EDGE) { @@ -1270,6 +1284,15 @@ SynapticsParseEventData(LocalDevicePtr local, SynapticsPrivatePtr priv, case BTN_3: /* multi-btn-3 */ priv->hwState.cbRight = (ev.value ? TRUE : FALSE); break; + case BTN_TOOL_FINGER: + priv->hwState.oneFinger = (ev.value ? TRUE : FALSE); + break; + case BTN_TOOL_DOUBLETAP: + priv->hwState.twoFingers = (ev.value ? TRUE : FALSE); + break; + case BTN_TOOL_TRIPLETAP: + priv->hwState.threeFingers = (ev.value ? TRUE : FALSE); + break; } break; case EV_ABS: @@ -1278,17 +1301,44 @@ SynapticsParseEventData(LocalDevicePtr local, SynapticsPrivatePtr priv, priv->hwState.x = ev.value; break; case ABS_Y: - priv->hwState.y = ev.value; + if (priv->swapY) { + priv->hwState.y = YMAX_NOMINAL + YMIN_NOMINAL - ev.value; + } else { + priv->hwState.y = ev.value; + } break; case ABS_PRESSURE: priv->hwState.z = ev.value; break; + case ABS_TOOL_WIDTH: + priv->hwState.fingerWidth = ev.value; + break; } break; case EV_MSC: switch (ev.code) { case MSC_GESTURE: - priv->hwState.w = ev.value; + priv->swapY = TRUE; + switch (ev.value) { + case 0: + priv->hwState.oneFinger = FALSE; + priv->hwState.twoFingers = TRUE; + priv->hwState.threeFingers = FALSE; + priv->hwState.fingerWidth = 5; + break; + case 1: + priv->hwState.oneFinger = FALSE; + priv->hwState.twoFingers = FALSE; + priv->hwState.threeFingers = TRUE; + priv->hwState.fingerWidth = 5; + break; + default: + priv->hwState.oneFinger = TRUE; + priv->hwState.twoFingers = FALSE; + priv->hwState.threeFingers = FALSE; + priv->hwState.fingerWidth = ev.value; + break; + } break; } break; @@ -1320,6 +1370,7 @@ SynapticsParseRawPacket(LocalDevicePtr local, SynapticsPrivatePtr priv, Bool ret = SynapticsGetPacket(local, priv); int newabs = SYN_MODEL_NEWABS(priv->model_id); unsigned char *buf; + int w; if (ret != Success) return ret; @@ -1335,9 +1386,9 @@ SynapticsParseRawPacket(LocalDevicePtr local, SynapticsPrivatePtr priv, buf[5]); hw->z = buf[2]; - hw->w = (((buf[0] & 0x30) >> 2) | - ((buf[0] & 0x04) >> 1) | - ((buf[3] & 0x04) >> 2)); + w = (((buf[0] & 0x30) >> 2) | + ((buf[0] & 0x04) >> 1) | + ((buf[3] & 0x04) >> 2)); hw->left = (buf[0] & 0x01) ? 1 : 0; hw->right = (buf[0] & 0x02) ? 1 : 0; @@ -1376,8 +1427,8 @@ SynapticsParseRawPacket(LocalDevicePtr local, SynapticsPrivatePtr priv, hw->z = (((buf[0] & 0x30) << 2) | (buf[3] & 0x3F)); - hw->w = (((buf[1] & 0x80) >> 4) | - ((buf[0] & 0x04) >> 1)); + w = (((buf[1] & 0x80) >> 4) | + ((buf[0] & 0x04) >> 1)); hw->left = (buf[0] & 0x01) ? 1 : 0; hw->right = (buf[0] & 0x02) ? 1 : 0; @@ -1385,6 +1436,14 @@ SynapticsParseRawPacket(LocalDevicePtr local, SynapticsPrivatePtr priv, hw->down = 0; hw->cbLeft = hw->cbRight = hw->up = hw->down = FALSE; } + + hw->y = YMAX_NOMINAL + YMIN_NOMINAL - hw->y; + + hw->oneFinger = FALSE; + hw->twoFingers = FALSE; + hw->threeFingers = FALSE; + hw->fingerWidth = 0; + if (hw->z > 0) { int w_ok = 0; /* @@ -1393,16 +1452,31 @@ SynapticsParseRawPacket(LocalDevicePtr local, SynapticsPrivatePtr priv, * normal width. */ if (SYN_CAP_EXTENDED(priv->capabilities)) { - if ((hw->w >= 0) && (hw->w <= 1)) { + if ((w >= 0) && (w <= 1)) { w_ok = SYN_CAP_MULTIFINGER(priv->capabilities); - } else if (hw->w == 2) { + } else if (w == 2) { w_ok = SYN_MODEL_PEN(priv->model_id); - } else if ((hw->w >= 4) && (hw->w <= 15)) { + } else if ((w >= 4) && (w <= 15)) { w_ok = SYN_CAP_PALMDETECT(priv->capabilities); } } if (!w_ok) - hw->w = 5; + w = 5; + + switch (w) { + case 0: + hw->twoFingers = TRUE; + hw->fingerWidth = 5; + break; + case 1: + hw->threeFingers = TRUE; + hw->fingerWidth = 5; + break; + default: + hw->oneFinger = TRUE; + hw->fingerWidth = w; + break; + } } priv->hwState = *hw; diff --git a/synaptics.h b/synaptics.h index 468f22b..dca94d9 100644 --- a/synaptics.h +++ b/synaptics.h @@ -13,7 +13,8 @@ typedef struct _SynapticsSHM /* Current device state */ int x, y; /* actual x, y coordinates */ int z; /* pressure value */ - int w; /* finger width value */ + int numFingers; /* number of fingers */ + int fingerWidth; /* finger width value */ int left, right, up, down; /* left/right/up/down buttons */ /* Probed hardware properties */ @@ -54,7 +55,11 @@ struct SynapticsHwState { int x; /* X position of finger */ int y; /* Y position of finger */ int z; /* Finger pressure */ - int w; /* Finger width/finger count */ + Bool oneFinger; + Bool twoFingers; + Bool threeFingers; + int fingerWidth; + Bool left; Bool right; Bool up; @@ -138,7 +143,10 @@ typedef struct _SynapticsPrivateRec int palm; /* Set to true when palm detected, reset to false when palm/finger contact disappears */ int prev_z; /* previous z value, for palm detection */ - int avg_w; /* weighted average of previous w values */ + int avg_width; /* weighted average of previous fingerWidth values */ + + Bool swapY; /* Swap Y coordinate direction. For compatibility + with old 2.5/2.6 kernels. Will be removed. */ } SynapticsPrivateRec, *SynapticsPrivatePtr; diff --git a/synclient.c b/synclient.c index e9f40fe..2aacacf 100644 --- a/synclient.c +++ b/synclient.c @@ -133,14 +133,15 @@ static void set_variables(SynapticsSHM* synshm, int argc, char* argv[], int firs static int is_equal(SynapticsSHM* s1, SynapticsSHM* s2) { - return ((s1->x == s2->x) && - (s1->y == s2->y) && - (s1->z == s2->z) && - (s1->w == s2->w) && - (s1->left == s2->left) && - (s1->right == s2->right) && - (s1->up == s2->up) && - (s1->down == s2->down)); + return ((s1->x == s2->x) && + (s1->y == s2->y) && + (s1->z == s2->z) && + (s1->numFingers == s2->numFingers) && + (s1->fingerWidth == s2->fingerWidth) && + (s1->left == s2->left) && + (s1->right == s2->right) && + (s1->up == s2->up) && + (s1->down == s2->down)); } static void monitor(SynapticsSHM* synshm, int delay) @@ -152,8 +153,9 @@ static void monitor(SynapticsSHM* synshm, int delay) while(1) { SynapticsSHM cur = *synshm; if (!is_equal(&old, &cur)) { - printf("x:%4d y:%4d z:%3d w:%2d left:%d right:%d up:%d down:%d\n", - cur.x, cur.y, cur.z, cur.w, cur.left, cur.right, cur.up, cur.down); + printf("x:%4d y:%4d z:%3d f:%1d w:%2d left:%d right:%d up:%d down:%d\n", + cur.x, cur.y, cur.z, cur.numFingers, cur.fingerWidth, + cur.left, cur.right, cur.up, cur.down); old = cur; } usleep(delay * 1000); |