diff options
Diffstat (limited to 'src/synaptics.c')
-rw-r--r-- | src/synaptics.c | 66 |
1 files changed, 65 insertions, 1 deletions
diff --git a/src/synaptics.c b/src/synaptics.c index 46f9ff2..9e151db 100644 --- a/src/synaptics.c +++ b/src/synaptics.c @@ -1031,6 +1031,7 @@ SynapticsReset(SynapticsPrivate * priv) priv->count_packet_finger = 0; priv->finger_state = FS_UNTOUCHED; priv->last_motion_millis = 0; + priv->inside_button_area = FALSE; priv->tap_state = TS_START; priv->tap_button = 0; priv->tap_button_state = TBS_BUTTON_UP; @@ -1531,6 +1532,56 @@ is_inside_sec_middlebutton_area(SynapticsParameters * para, int x, int y) return is_inside_button_area(para, TOP_MIDDLE_BUTTON_AREA, x, y); } +static Bool +is_inside_top_or_bottom_button_area(SynapticsParameters * para, int offset, + int x, int y) +{ + Bool inside_area = TRUE; + Bool right_valid, middle_valid; + int top, bottom; + + /* We don't have a left button area, so we only check the y axis */ + right_valid = para->softbutton_areas[offset][TOP] || + para->softbutton_areas[offset][BOTTOM]; + middle_valid = para->softbutton_areas[offset + 1][TOP] || + para->softbutton_areas[offset + 1][BOTTOM]; + + if (!right_valid && !middle_valid) + return FALSE; + + /* Check both buttons are horizontally aligned */ + if (right_valid && middle_valid && ( + para->softbutton_areas[offset][TOP] != + para->softbutton_areas[offset + 1][TOP] || + para->softbutton_areas[offset][BOTTOM] != + para->softbutton_areas[offset + 1][BOTTOM])) + return FALSE; + + if (right_valid) { + top = para->softbutton_areas[offset][TOP]; + bottom = para->softbutton_areas[offset][BOTTOM]; + } + else { + top = para->softbutton_areas[offset + 1][TOP]; + bottom = para->softbutton_areas[offset + 1][BOTTOM]; + } + + if (top && y < top) + inside_area = FALSE; + else if (bottom && y > bottom) + inside_area = FALSE; + + return inside_area; +} + +static Bool +is_inside_anybutton_area(SynapticsParameters * para, int x, int y) +{ + return + is_inside_top_or_bottom_button_area(para, BOTTOM_BUTTON_AREA, x, y) || + is_inside_top_or_bottom_button_area(para, TOP_BUTTON_AREA, x, y); +} + static CARD32 timerFunc(OsTimerPtr timer, CARD32 now, pointer arg) { @@ -3013,6 +3064,8 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, int delay = 1000000000; int timeleft; Bool inside_active_area; + Bool using_cumulative_coords = FALSE; + Bool ignore_motion; /* If touchpad is switched off, we skip the whole thing and return delay */ if (para->touchpad_off == TOUCHPAD_OFF) { @@ -3038,6 +3091,7 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, if (para->clickpad && (hw->left || hw->right || hw->middle)) { hw->x = hw->cumulative_dx; hw->y = hw->cumulative_dy; + using_cumulative_coords = TRUE; } /* apply hysteresis before doing anything serious. This cancels @@ -3047,6 +3101,16 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, inside_active_area = is_inside_active_area(priv, hw->x, hw->y); + /* Ignore motion *starting* inside softbuttonareas */ + if (priv->finger_state < FS_TOUCHED) + priv->inside_button_area = is_inside_anybutton_area(para, hw->x, hw->y); + /* If we already have a finger down, clear inside_button_area if it goes + outside of the softbuttonareas */ + else if (priv->inside_button_area && !is_inside_anybutton_area(para, hw->x, hw->y)) + priv->inside_button_area = FALSE; + + ignore_motion = !using_cumulative_coords && priv->inside_button_area; + /* these two just update hw->left, right, etc. */ update_hw_button_state(pInfo, hw, now, &delay); if (priv->has_scrollbuttons) @@ -3118,7 +3182,7 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, } /* Post events */ - if (finger >= FS_TOUCHED && (dx || dy)) + if (finger >= FS_TOUCHED && (dx || dy) && !ignore_motion) xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy); if (priv->mid_emu_state == MBE_LEFT_CLICK) { |