From 3dec56a50976cf2470482566e4dfec4007cbdf43 Mon Sep 17 00:00:00 2001 From: Erkin Bahceci Date: Mon, 6 Apr 2009 09:11:27 -0500 Subject: [PATCH] Make click-and-drag work for Macbook5,1+ This makes click-and-drag work for touchpads with integrated button. --- usr/src/dkms_source_tree/bcm5974.c | 70 +++++++++++++++++++++++++++++++++--- 1 files changed, 65 insertions(+), 5 deletions(-) diff --git a/usr/src/dkms_source_tree/bcm5974.c b/usr/src/dkms_source_tree/bcm5974.c index ef2ffab..6069d2e 100644 --- a/usr/src/dkms_source_tree/bcm5974.c +++ b/usr/src/dkms_source_tree/bcm5974.c @@ -103,6 +103,11 @@ static int debug = 1; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Activate debugging output"); +/* constants used to distinguish two-finger-clicking and click-and-drag + * on touchpads with integrated button */ +#define TWO_FINGERS_MAX_DIST_SQR (4500 * 4500) +#define MIN_THUMB_WIDTH 1300 + /* button data structure */ struct bt_data { u8 unknown1; /* constant */ @@ -323,9 +328,15 @@ static int report_tp_state(struct bcm5974 *dev, int size) const struct tp_finger *f; struct input_dev *input = dev->input; int raw_p, raw_w, raw_x, raw_y, raw_n; + int second_raw_x, second_raw_y, second_raw_w; int ptest = 0, origin = 0, ibt = 0, nmin = 0, nmax = 0; int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; + /* state variables used to distinguish two-finger-clicking and + * click-and-drag on touchpads with integrated button */ + static bool click_started_with_two_fingers = false; + static int last_ibt = 0; + if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0) return -EIO; @@ -334,21 +345,70 @@ static int report_tp_state(struct bcm5974 *dev, int size) /* always track the first finger; when detached, start over */ if (raw_n) { - raw_p = raw2int(f->force_major); raw_w = raw2int(f->size_major); raw_x = raw2int(f->abs_x); raw_y = raw2int(f->abs_y); + if (HAS_INTEGRATED_BUTTON(c)) { + if (raw_n == 2) { + /* Get second finger data */ + second_raw_w = raw2int((f+1)->size_major); + second_raw_x = raw2int((f+1)->abs_x); + second_raw_y = raw2int((f+1)->abs_y); + } + + /* set the integrated button */ + ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); + + /* if just started clicking */ + if (!last_ibt && ibt) { + if (raw_n == 2 && + /* neither finger is likely to be the thumb + * (i.e. neither is too wide) */ + raw_w < MIN_THUMB_WIDTH && + second_raw_w < MIN_THUMB_WIDTH && + /* the two fingers are not too separated */ + ((second_raw_x - raw_x) * + (second_raw_x - raw_x) + + (second_raw_y - raw_y) * + (second_raw_y - raw_y) < TWO_FINGERS_MAX_DIST_SQR)) + click_started_with_two_fingers = true; + } + else if (!ibt && click_started_with_two_fingers) + click_started_with_two_fingers = false; + + /* keep the last ibt value in static variable */ + last_ibt = ibt; + + /* if currently clicking and two fingers are touching the trackpad + * but initial clicking was not done with two fingers */ + if (!click_started_with_two_fingers && ibt && raw_n == 2) { + /* if the second finger is the clicking one (i.e. is below), + * ignore that finger and track the first finger */ + if (second_raw_y < raw_y) { + raw_n--; + } + /* if the first finger is the clicking one (i.e. is below), + * ignore that finger and track the second finger */ + else + { + f++; + raw_n--; + raw_w = second_raw_w; + raw_x = second_raw_x; + raw_y = second_raw_y; + } + } + } + + raw_p = raw2int(f->force_major); + dprintk(9, "bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d " "n: %d\n", raw_p, raw_w, raw_x, raw_y, raw_n); ptest = int2bound(&c->p, raw_p); origin = raw2int(f->origin); - - /* set the integrated button if applicable */ - if (c->tp_type == TYPE2) - ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); } /* while tracking finger still valid, count all fingers */ -- 1.6.0.4