Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:11.4
xorg-x11-driver-input
xf86-input-synaptics-clickpad-threshold.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File xf86-input-synaptics-clickpad-threshold.diff of Package xorg-x11-driver-input
--- include/synaptics-properties.h | 6 + man/synaptics.man | 30 ++++++- src/properties.c | 15 +++ src/synaptics.c | 156 ++++++++++++++++++++++++++++++----------- src/synapticsstr.h | 5 + tools/synclient.c | 2 6 files changed, 169 insertions(+), 45 deletions(-) --- a/include/synaptics-properties.h +++ b/include/synaptics-properties.h @@ -155,6 +155,12 @@ /* 32 bit, 4 values, left, right, top, bottom */ #define SYNAPTICS_PROP_AREA "Synaptics Area" +/* 32bit */ +#define SYNAPTICS_PROP_TOUCH_BUTTON_AREA "Synaptics Touch Button Area" + +/* 32bit */ +#define SYNAPTICS_PROP_TOUCH_BUTTON_STICKY "Synapyics Touch Button Sticky" + /* 8 bit (BOOL, read-only), has_led */ #define SYNAPTICS_PROP_LED "Synaptics LED" --- a/src/properties.c +++ b/src/properties.c @@ -82,6 +82,8 @@ Atom prop_capabilities = 0; Atom prop_resolution = 0; Atom prop_area = 0; +Atom prop_touch_button_area = 0; +Atom prop_touch_button_sticky = 0; Atom prop_led = 0; Atom prop_led_status = 0; Atom prop_led_double_tap = 0; @@ -282,6 +284,9 @@ values[3] = para->area_bottom_edge; prop_area = InitAtom(local->dev, SYNAPTICS_PROP_AREA, 32, 4, values); + prop_touch_button_area = InitAtom(local->dev, SYNAPTICS_PROP_TOUCH_BUTTON_AREA, 32, 1, ¶->touch_button_area); + prop_touch_button_sticky = InitAtom(local->dev, SYNAPTICS_PROP_TOUCH_BUTTON_STICKY, 32, 1, ¶->touch_button_sticky); + prop_led = InitAtom(local->dev, SYNAPTICS_PROP_LED, 8, 1, ¶->has_led); prop_led_status = InitAtom(local->dev, SYNAPTICS_PROP_LED_STATUS, 8, 1, ¶->led_status); @@ -671,6 +676,16 @@ para->area_right_edge = area[1]; para->area_top_edge = area[2]; para->area_bottom_edge = area[3]; + } else if (property == prop_touch_button_area) { + if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER) + return BadMatch; + + para->touch_button_area = *(INT32*)prop->data; + } else if (property == prop_touch_button_sticky) { + if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER) + return BadMatch; + + para->touch_button_sticky = *(INT32*)prop->data; } else if (property == prop_led_status) { if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER) --- a/src/synaptics.c +++ b/src/synaptics.c @@ -511,18 +511,6 @@ 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); @@ -531,10 +519,6 @@ pars->area_top_edge = set_percent_option(opts, "AreaTopEdge", height, priv->miny); pars->area_bottom_edge = set_percent_option(opts, "AreaBottomEdge", height, priv->miny); - /* in clickpad mode, we don't want to sense the button area as default */ - if (pars->area_bottom_edge == 0 && priv->is_clickpad) - pars->area_bottom_edge = b; - pars->area_left_edge = set_percent_option(opts, "AreaLeftEdge", width, priv->minx); pars->area_right_edge = set_percent_option(opts, "AreaRightEdge", width, priv->minx); @@ -604,6 +588,8 @@ pars->tap_and_drag_gesture = xf86SetBoolOption(opts, "TapAndDragGesture", TRUE); pars->resolution_horiz = xf86SetIntOption(opts, "HorizResolution", horizResolution); pars->resolution_vert = xf86SetIntOption(opts, "VertResolution", vertResolution); + pars->touch_button_area = xf86SetIntOption(opts, "TouchButtonArea", 20); + pars->touch_button_sticky = xf86SetIntOption(opts, "TouchButtonSticky", 64); pars->led_double_tap = xf86SetBoolOption(opts, "LEDDoubleTap", TRUE); /* Warn about (and fix) incorrectly configured TopEdge/BottomEdge parameters */ @@ -1086,6 +1072,11 @@ return Success; } +static void +SetTapState(SynapticsPrivate *priv, enum TapState tap_state, int millis); +static void +SetMovingState(SynapticsPrivate *priv, enum MovingState moving_state, int millis); + #define LED_TOGGLE_X_AREA 0.10 #define LED_TOGGLE_Y_AREA 0.08 @@ -1152,45 +1143,118 @@ return 0; /* already processed; ignore this finger event */ } +static void +get_clickpad_button(SynapticsPrivate *priv, struct SynapticsHwState *hw, + int button_x) +{ + 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 (button_x < left_button_x) + hw->left = 1; + else if (button_x > right_button_x) + hw->right = 1; + else + hw->middle = 1; +} + +static inline int get_touch_button_area(SynapticsPrivate *priv) +{ + SynapticsParameters *para = &priv->synpara; + return priv->maxy - (priv->maxy - priv->miny) * para->touch_button_area / 100; +} + +#define is_main_bottom_edge(hw, priv) \ + ((hw)->y >= get_touch_button_area(priv)) + +static void reset_state_as_moving(SynapticsPrivate *priv, struct SynapticsHwState *hw) +{ + SynapticsParameters *para = &priv->synpara; + + if (hw->z >= para->finger_low) { + SetMovingState(priv, MS_TOUCHPAD_RELATIVE, hw->millis); + SetTapState(priv, TS_MOVE, hw->millis); + priv->touch_on.x = hw->x; + priv->touch_on.y = hw->y; + priv->touch_on.millis = hw->millis; + } + priv->tap_button = 0; +} + /* clickpad event handling */ static void handle_clickpad(LocalDevicePtr local, struct SynapticsHwState *hw) { SynapticsPrivate *priv = (SynapticsPrivate *) (local->private); SynapticsParameters *para = &priv->synpara; + int in_main_button; + + in_main_button = is_main_bottom_edge(hw, priv); + if (in_main_button) { + if (hw->left) { + /* when button is pressed solely, don't move and ignore tapping */ + hw->z = 0; + priv->count_packet_finger = 0; + priv->ignore_tapping = TRUE; + SetMovingState(priv, MS_FALSE, hw->millis); + SetTapState(priv, TS_START, hw->millis); + priv->tap_button = 0; + } else if (hw->z < para->finger_low) { + priv->ignore_tapping = FALSE; + } + } else { + priv->ignore_tapping = FALSE; + } if (hw->left) { /* clicked? */ - if (hw->y > para->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 - */ - 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; - } else { - /* dragging */ + if (priv->prev_hw.left || priv->prev_hw.right || priv->prev_hw.middle) { + /* already dragging, just copy the previous button state */ hw->left = priv->prev_hw.left; hw->right = priv->prev_hw.right; hw->middle = priv->prev_hw.middle; + } else if (in_main_button) { + /* start dragging */ + hw->left = 0; + if (in_main_button) + get_clickpad_button(priv, hw, hw->x); } + } else { + /* button being released, reset dragging if necessary */ + if (priv->prev_hw.left || priv->prev_hw.right || priv->prev_hw.middle) { + priv->count_packet_finger = 0; + reset_state_as_moving(priv, hw); + } + hw->left = hw->right = hw->middle = 0; + } + + if (in_main_button && para->touch_button_sticky > 0) { + if (!priv->count_packet_finger) { + /* if the primary track point is in the button area, be sticky */ + priv->clickpad_threshold = para->touch_button_sticky; + priv->clickpad_dx = priv->clickpad_dy = 0; + } + } else { + /* outside the button area, clear stickiness */ + priv->clickpad_threshold = 0; } priv->prev_hw = *hw; } +static int +move_distance(int dx, int dy) +{ + return sqrt(SQR(dx) + SQR(dy)); +} + /* * Convert from absolute X/Y coordinates to a coordinate system where * -1 corresponds to the left/upper edge and +1 corresponds to the @@ -1667,7 +1731,7 @@ int timeleft, timeout; int delay = 1000000000; - if (priv->palm) + if (priv->palm || priv->ignore_tapping) return delay; touch = finger && !priv->finger_state; @@ -2372,6 +2436,8 @@ if (para->touchpad_off != 1 && priv->is_clickpad) handle_clickpad(local, hw); + priv->prev_hw = *hw; + /* Treat the first two multi buttons as up/down for now. */ hw->up |= hw->multi[0]; hw->down |= hw->multi[1]; @@ -2554,6 +2620,14 @@ } timeleft = ComputeDeltas(priv, hw, edge, &dx, &dy, inside_active_area); + if (priv->clickpad_threshold > 0) { + priv->clickpad_dx += dx; + priv->clickpad_dy += dy; + if (move_distance(priv->clickpad_dx, priv->clickpad_dy) > priv->clickpad_threshold) + priv->clickpad_threshold = 0; + else + dx = dy = 0; + } delay = MIN(delay, timeleft); @@ -2565,7 +2639,7 @@ (hw->multi[2] ? 0x20 : 0) | (hw->multi[3] ? 0x40 : 0)); - if (priv->tap_button > 0) { + if (priv->tap_button > 0 && !priv->ignore_tapping) { int tap_mask = 1 << (priv->tap_button - 1); if (priv->tap_button_state == TBS_BUTTON_DOWN_UP) { if (tap_mask != (priv->lastButtons & tap_mask)) { --- a/src/synapticsstr.h +++ b/src/synapticsstr.h @@ -160,6 +160,8 @@ 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 touch_button_area; /* clickpad button area */ + int touch_button_sticky; /* pointer stickiness in button area */ Bool has_led; /* has an embedded LED */ Bool led_status; /* Current status of LED (1=on) */ Bool led_double_tap; /* double-tap period in ms for touchpad LED control */ @@ -239,6 +241,9 @@ Bool has_width; /* device reports finger width */ Bool has_scrollbuttons; /* device has physical scrollbuttons */ Bool is_clickpad; /* is Clickpad device (one-button) */ + Bool ignore_tapping; + unsigned int clickpad_threshold; + int clickpad_dx, clickpad_dy; struct SynapticsHwState prev_hw; /* previous h/w state (for clickpad) */ int prop_change_pending; Bool led_touch_state; --- a/tools/synclient.c +++ b/tools/synclient.c @@ -143,6 +143,8 @@ {"AreaRightEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 1}, {"AreaTopEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 2}, {"AreaBottomEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 3}, + {"TouchButtonArea", PT_INT, 0, 100, SYNAPTICS_PROP_TOUCH_BUTTON_AREA, 32, 0}, + {"TouchButtonSticky", PT_INT, 0, 1000, SYNAPTICS_PROP_TOUCH_BUTTON_STICKY, 32, 0}, {"LEDStatus", PT_BOOL, 0, 1, SYNAPTICS_PROP_LED_STATUS, 8, 0}, {"LEDDoubleTap", PT_BOOL, 0, 1, SYNAPTICS_PROP_LED_DOUBLE_TAP, 8, 0}, { NULL, 0, 0, 0, 0 } --- a/man/synaptics.man +++ b/man/synaptics.man @@ -554,6 +554,21 @@ "untouch" event happens when the Z value goes below FingerLow. . .TP +.BI "Option \*qTouchButtonArea\*q \*q" integer \*q +. +Provides the size of the click-button area for ClickPad devices in +percent. As default, it's 20. +Property: "Synaptics Touch Button Area" +. +.TP +.BI "Option \*qTouchButtonSticky\*q \*q" integer \*q +. +Provides the threshold to start moving in the click-button area. The +higher value is set, the pointer becomes sticky in the click-button +area. The default value is 64. +Property: "Synaptics Touch Button Sticky" +. +.TP .BI "Option \*qLEDDoubleTap\*q \*q" boolean \*q . Enables/disables the touchpad-control by double-tapping on the top-left @@ -744,10 +759,9 @@ and without multi-fingers, the driver assumes it's a Synaptics Clickpad device and handles it in ClickZone mode. In this mode, a left/right/middle button event is generated according to the -position you click. When Clickpad is enabled, the touchpad area -is shrunk as default in 20% and the bottom area is used as the -click-button area. The area can be configurable via options or -properties below. +position you click. When Clickpad is enabled, the bottom area (as +default 20%) is used as the click-button area. The size of the area +is configurable via options or properties below. .SH "DEVICE PROPERTIES" Synaptics 1.0 and higher support input device properties if the driver is @@ -923,6 +937,14 @@ 32 bit unsigned, 2 values (read-only), vertical, horizontal in units/millimeter. .TP 7 +.BI "Synaptics Touch Button Area" +32 bit. + +.TP 7 +.BI "Synaptics Touch Button Sticky" +32 bit. + +.TP 7 .BI "Synaptics LED" 8 bit (BOOL, read-only), indicating whether the device has an embedded LED support or not.
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor