From patchwork Wed Apr 21 09:02:48 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 93837 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o3L93Kew027469 for ; Wed, 21 Apr 2010 09:03:20 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753158Ab0DUJCw (ORCPT ); Wed, 21 Apr 2010 05:02:52 -0400 Received: from cantor2.suse.de ([195.135.220.15]:37251 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752897Ab0DUJCu convert rfc822-to-8bit (ORCPT ); Wed, 21 Apr 2010 05:02:50 -0400 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.221.2]) by mx2.suse.de (Postfix) with ESMTP id 0A78D5FC9F; Wed, 21 Apr 2010 11:02:48 +0200 (CEST) Date: Wed, 21 Apr 2010 11:02:48 +0200 Message-ID: From: Takashi Iwai To: Jian-feng Ding Cc: linux-input@vger.kernel.org Subject: Re: some questions about Synaptics Clickpad driver patch In-Reply-To: <20100421084058.GS15241@djf-karmic.localdomain> References: <20100421084058.GS15241@djf-karmic.localdomain> User-Agent: Wanderlust/2.15.6 (Almost Unreal) SEMI/1.14.6 (Maruoka) FLIM/1.14.9 (=?UTF-8?B?R29qxY0=?=) APEL/10.7 Emacs/23.1 (x86_64-suse-linux-gnu) MULE/6.0 (HANACHIRUSATO) MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Wed, 21 Apr 2010 09:03:20 +0000 (UTC) diff --git a/src/eventcomm.c b/src/eventcomm.c index d00d810..10d183d 100644 --- a/src/eventcomm.c +++ b/src/eventcomm.c @@ -252,6 +252,12 @@ event_query_axis_ranges(LocalDevicePtr local) if ((priv->has_triple = (TEST_BIT(BTN_TOOL_TRIPLETAP, keybits) != 0))) strcat(buf, " triple"); xf86Msg(X_INFO, "%s: buttons:%s\n", local->name, buf); + + /* clickpad device reports only the single left button mask */ + if (priv->has_left && !priv->has_right && !priv->has_middle) { + priv->is_clickpad = TRUE; + xf86Msg(X_INFO, "%s: is Clickpad device\n", local->name); + } } } diff --git a/src/synaptics.c b/src/synaptics.c index 091dbe1..951b3fa 100644 --- a/src/synaptics.c +++ b/src/synaptics.c @@ -457,6 +457,18 @@ static void set_default_parameters(LocalDevicePtr local) vertResolution = priv->resy; } + /* Clickpad mode -- bottom area is used as buttons */ + if (priv->is_clickpad) { + int button_bottom; + /* Clickpad devices usually the button area at the bottom, and + * its size seems ca. 20% of the touchpad height no matter how + * large the pad is. + */ + button_bottom = priv->maxy - (abs(priv->maxy - priv->miny) * 20) / 100; + if (button_bottom < b && button_bottom >= t) + b = button_bottom; + } + /* set the parameters */ pars->left_edge = xf86SetIntOption(opts, "LeftEdge", l); pars->right_edge = xf86SetIntOption(opts, "RightEdge", r); @@ -2052,6 +2064,59 @@ HandleClickWithFingers(SynapticsParameters *para, struct SynapticsHwState *hw) } } +/* clickpad event handling */ +static void +HandleClickpad(LocalDevicePtr local, struct SynapticsHwState *hw, edge_type edge) +{ + SynapticsPrivate *priv = (SynapticsPrivate *) (local->private); + SynapticsParameters *para = &priv->synpara; + + if (edge & BOTTOM_EDGE) { + /* button area */ + int width = priv->maxx - priv->minx; + int left_button_x, right_button_x; + + /* left and right clickpad button ranges; + * the gap between them is interpreted as a middle-button click + */ + left_button_x = width * 2/ 5 + priv->minx; + right_button_x = width * 3 / 5 + priv->minx; + + /* clickpad reports only one button, and we need + * to fake left/right buttons depending on the touch position + */ + if (hw->left) { /* clicked? */ + hw->left = 0; + if (hw->x < left_button_x) + hw->left = 1; + else if (hw->x > right_button_x) + hw->right = 1; + else + hw->middle = 1; + } + + /* Don't move pointer position in the button area during clicked, + * except for horiz/vert scrolling is enabled. + * + * The synaptics driver tends to be pretty sensitive. This hack + * is to avoid that the pointer moves slightly and misses the + * poistion you aimed to click. + * + * Also, when the pointer movement is reported, the dragging + * (with a sort of multi-touching) doesn't work well, too. + */ + if (hw->left || !(para->scroll_edge_horiz || + ((edge & RIGHT_EDGE) && para->scroll_edge_vert))) + hw->z = 0; /* don't move pointer */ + + } else if (hw->left) { + /* dragging */ + hw->left = priv->prev_hw.left; + hw->right = priv->prev_hw.right; + hw->middle = priv->prev_hw.middle; + } + priv->prev_hw = *hw; +} /* * React on changes in the hardware state. This function is called every time @@ -2102,6 +2167,12 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState *hw) if (para->touchpad_off == 1) return delay; + edge = edge_detection(priv, hw->x, hw->y); + + /* Clickpad handling for button area */ + if (priv->is_clickpad) + HandleClickpad(local, hw, edge); + /* Treat the first two multi buttons as up/down for now. */ hw->up |= hw->multi[0]; hw->down |= hw->multi[1]; @@ -2152,7 +2223,6 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState *hw) hw->multi[2] = hw->multi[3] = FALSE; } - edge = edge_detection(priv, hw->x, hw->y); inside_active_area = is_inside_active_area(priv, hw->x, hw->y); finger = SynapticsDetectFinger(priv, hw); diff --git a/src/synapticsstr.h b/src/synapticsstr.h index bd19c79..05e43d3 100644 --- a/src/synapticsstr.h +++ b/src/synapticsstr.h @@ -232,6 +232,8 @@ typedef struct _SynapticsPrivateRec Bool has_double; /* double click detected for this device */ Bool has_triple; /* triple click detected for this device */ Bool has_pressure; /* device reports pressure */ + Bool is_clickpad; /* is Clickpad device (one-button) */ + struct SynapticsHwState prev_hw; /* previous h/w state (for clickpad) */ enum TouchpadModel model; /* The detected model */ } SynapticsPrivate;