/* Monitors for 1 finger touch and forces left button press or 1 finger * release and will remove left button press. * * This function relies on wcmGestureMode will only be zero if * WACOM_GESTURE_LAG_TIME has passed and still ony 1 finger on screen. */ static void wcmSingleFingerPress(WacomDevicePtr priv) { WacomCommonPtr common = priv->common; WacomChannelPtr firstChannel = getContactNumber(common, 0); WacomChannelPtr secondChannel = getContactNumber(common, 1); Bool firstInProx = firstChannel && firstChannel->valid.states[0].proximity; Bool secondInProx = secondChannel && secondChannel->valid.states[0].proximity; DBG(10, priv, "\n"); /* This gesture is only valid on touchscreens. */ if (!TabletHasFeature(priv->common, WCM_LCD)) return; if (!firstChannel) return; if (firstInProx && !secondInProx) { firstChannel->valid.states[0].buttons |= 1; common->wcmGestureMode = GESTURE_DRAG_MODE; } else { firstChannel->valid.states[0].buttons &= ~1; common->wcmGestureMode = GESTURE_NONE_MODE; } }
/* A single finger tap is defined as 1 finger tap that lasts less than * wcmTapTime. It results in a left button press. * * Some work must be done to make sure two fingers were not touching * during this gesture. This is easy if first finger is released * first. To handle case of second finger released first, require * second finger to have been released before first finger ever touched. * * Function relies on ds[0/1].sample to be updated only when entering or * exiting proximity so no storage is needed when initial touch occurs. */ static void wcmSingleFingerTap(WacomDevicePtr priv) { WacomCommonPtr common = priv->common; WacomDeviceState ds[2] = {}, dsLast[2] = {}; getStateHistory(common, ds, ARRAY_SIZE(ds), 0); getStateHistory(common, dsLast, ARRAY_SIZE(dsLast), 1); DBG(10, priv, "\n"); /* This gesture is only valid on touchpads. */ if (TabletHasFeature(priv->common, WCM_LCD)) return; if (!ds[0].proximity && dsLast[0].proximity && !ds[1].proximity) { /* Single Tap must have lasted less than wcmTapTime * and second finger must not have released after * first finger touched. */ if (ds[0].sample - dsLast[0].sample <= common->wcmGestureParameters.wcmTapTime && ds[1].sample < dsLast[0].sample) { common->wcmGestureMode = GESTURE_PREDRAG_MODE; /* Delay to detect possible drag operation */ TimerSet(priv->tap_timer, 0, common->wcmGestureParameters.wcmTapTime, wcmSingleFingerTapTimer, priv); } } }
/** * Send multitouch events. If entering multitouch mode (indicated by * GESTURE_LAG_MODE), then touch events are sent for all in-prox * contacts. Otherwise, only the specified contact has a touch event * generated. * * @param[in] priv * @param[in] contact_id ID of the contact to send event for (at minimum) */ static void wcmFingerMultitouch(WacomDevicePtr priv, int contact_id) { Bool lag_mode = priv->common->wcmGestureMode == GESTURE_LAG_MODE; Bool prox = FALSE; int i; if (lag_mode && TabletHasFeature(priv->common, WCM_LCD)) { /* wcmSingleFingerPress triggers a button press as * soon as a single finger appears. ensure we release * that button before getting too far along */ wcmSendButtonClick(priv, 1, 0); } for (i = 0; i < MAX_CHANNELS; i++) { WacomChannelPtr channel = priv->common->wcmChannel+i; WacomDeviceState state = channel->valid.state; if (state.device_type != TOUCH_ID) continue; if (lag_mode || state.serial_num == contact_id + 1) { wcmSendTouchEvent(priv, channel, lag_mode); } prox |= state.proximity; } if (!prox) priv->common->wcmGestureMode = GESTURE_NONE_MODE; else if (lag_mode) priv->common->wcmGestureMode = GESTURE_MULTITOUCH_MODE; }
/* A single finger tap is defined as 1 finger tap that lasts less than * wcmTapTime. It results in a left button press. * * Some work must be done to make sure two fingers were not touching * during this gesture. This is easy if first finger is released * first. To handle case of second finger released first, require * second finger to have been released before first finger ever touched. * * Function relies on ds[0/1].sample to be updated only when entering or * exiting proximity so no storage is needed when initial touch occurs. */ static void wcmSingleFingerTap(WacomDevicePtr priv) { WacomCommonPtr common = priv->common; WacomChannelPtr firstChannel = common->wcmChannel; WacomChannelPtr secondChannel = common->wcmChannel + 1; WacomDeviceState ds[2] = { firstChannel->valid.states[0], secondChannel->valid.states[0] }; WacomDeviceState dsLast[2] = { firstChannel->valid.states[1], secondChannel->valid.states[1] }; DBG(10, priv, "\n"); /* This gesture is only valid on touchpads. */ if (TabletHasFeature(priv->common, WCM_LCD)) return; if (!ds[0].proximity && dsLast[0].proximity && !ds[1].proximity) { /* Single Tap must have lasted less than wcmTapTime * and second finger must not have released after * first finger touched. */ if (ds[0].sample - dsLast[0].sample <= common->wcmGestureParameters.wcmTapTime && ds[1].sample < dsLast[0].sample) { common->wcmGestureMode = GESTURE_PREDRAG_MODE; /* Delay to detect possible drag operation */ TimerSet(NULL, 0, common->wcmGestureParameters.wcmTapTime, wcmSingleFingerTapTimer, priv); } } }
/* Monitors for 1 finger touch and forces left button press or 1 finger * release and will remove left button press. * * This function relies on wcmGestureMode will only be zero if * WACOM_GESTURE_LAG_TIME has passed and still ony 1 finger on screen. */ static void wcmSingleFingerPress(WacomDevicePtr priv) { WacomCommonPtr common = priv->common; WacomChannelPtr firstChannel = common->wcmChannel; WacomChannelPtr secondChannel = common->wcmChannel + 1; WacomDeviceState ds[2] = { firstChannel->valid.states[0], secondChannel->valid.states[0] }; DBG(10, priv, "\n"); /* This gesture is only valid on touchscreens. */ if (!TabletHasFeature(priv->common, WCM_LCD)) return; if (ds[0].proximity && !ds[1].proximity) firstChannel->valid.states[0].buttons |= 1; if (!ds[0].proximity && !ds[1].proximity) firstChannel->valid.states[0].buttons &= ~1; }