/** * Send a touch event for the provided contact ID. This makes use of * the multitouch API available in XI2.2. * * @param[in] priv * @param[in] channel Channel to send a touch event for * @param[in] no_update If 'true', TouchUpdate events will not be created. * This should be used when entering multitouch mode to ensure TouchBegin * events are sent for already-in-prox contacts. */ static void wcmSendTouchEvent(WacomDevicePtr priv, WacomChannelPtr channel, Bool no_update) { #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 16 ValuatorMask *mask = priv->common->touch_mask; WacomDeviceState state = channel->valid.state; WacomDeviceState oldstate = channel->valid.states[1]; int type = -1; wcmRotateAndScaleCoordinates (priv->pInfo, &state.x, &state.y); valuator_mask_set(mask, 0, state.x); valuator_mask_set(mask, 1, state.y); if (!state.proximity) { DBG(6, priv->common, "This is a touch end event\n"); type = XI_TouchEnd; } else if (!oldstate.proximity || no_update) { DBG(6, priv->common, "This is a touch begin event\n"); type = XI_TouchBegin; } else { DBG(6, priv->common, "This is a touch update event\n"); type = XI_TouchUpdate; } xf86PostTouchEvent(priv->pInfo->dev, state.serial_num - 1, type, 0, mask); #endif }
/** * Sets a range of valuators between first_valuator and num_valuators with * the data in the valuators array. All other values are set to 0. */ void valuator_mask_set_range(ValuatorMask *mask, int first_valuator, int num_valuators, const int* valuators) { int i; valuator_mask_zero(mask); for (i = first_valuator; i < min(first_valuator + num_valuators, MAX_VALUATORS); i++) valuator_mask_set(mask, i, valuators[i - first_valuator]); }
/** * Originally a part of xf86PostMotionEvent; modifies valuators * in-place. Retained mostly for embedded scenarios. */ void acceleratePointerLightweight( DeviceIntPtr dev, ValuatorMask* val, CARD32 ignored) { float mult = 0.0, tmpf; int dx = 0, dy = 0, tmpi; if (valuator_mask_isset(val, 0)) { dx = valuator_mask_get(val, 0); } if (valuator_mask_isset(val, 1)) { dy = valuator_mask_get(val, 1); } if (!dx && !dy) return; if (dev->ptrfeed && dev->ptrfeed->ctrl.num) { /* modeled from xf86Events.c */ if (dev->ptrfeed->ctrl.threshold) { if ((abs(dx) + abs(dy)) >= dev->ptrfeed->ctrl.threshold) { tmpf = ((float)dx * (float)(dev->ptrfeed->ctrl.num)) / (float)(dev->ptrfeed->ctrl.den) + dev->last.remainder[0]; if (dx) { tmpi = (int) tmpf; valuator_mask_set(val, 0, tmpi); dev->last.remainder[0] = tmpf - (float)tmpi; } tmpf = ((float)dy * (float)(dev->ptrfeed->ctrl.num)) / (float)(dev->ptrfeed->ctrl.den) + dev->last.remainder[1]; if (dy) { tmpi = (int) tmpf; valuator_mask_set(val, 1, tmpi); dev->last.remainder[1] = tmpf - (float)tmpi; } } } else { mult = pow((float)dx * (float)dx + (float)dy * (float)dy, ((float)(dev->ptrfeed->ctrl.num) / (float)(dev->ptrfeed->ctrl.den) - 1.0) / 2.0) / 2.0; if (dx) { tmpf = mult * (float)dx + dev->last.remainder[0]; tmpi = (int) tmpf; valuator_mask_set(val, 0, tmpi); dev->last.remainder[0] = tmpf - (float)tmpi; } if (dy) { tmpf = mult * (float)dy + dev->last.remainder[1]; tmpi = (int)tmpf; valuator_mask_set(val, 1, tmpi); dev->last.remainder[1] = tmpf - (float)tmpi; } } } }
/** * Modifies valuators in-place. * This version employs a velocity approximation algorithm to * enable fine-grained predictable acceleration profiles. */ void acceleratePointerPredictable( DeviceIntPtr dev, ValuatorMask* val, CARD32 evtime) { float fdx, fdy, tmp, mult; /* no need to init */ int dx = 0, dy = 0, tmpi; DeviceVelocityPtr velocitydata = GetDevicePredictableAccelData(dev); Bool soften = TRUE; if (!velocitydata) return; if (velocitydata->statistics.profile_number == AccelProfileNone && velocitydata->const_acceleration == 1.0f) { return; /*we're inactive anyway, so skip the whole thing.*/ } if (valuator_mask_isset(val, 0)) { dx = valuator_mask_get(val, 0); } if (valuator_mask_isset(val, 1)) { dy = valuator_mask_get(val, 1); } if (dx || dy){ /* reset non-visible state? */ if (ProcessVelocityData2D(velocitydata, dx , dy, evtime)) { soften = FALSE; } if (dev->ptrfeed && dev->ptrfeed->ctrl.num) { /* invoke acceleration profile to determine acceleration */ mult = ComputeAcceleration (dev, velocitydata, dev->ptrfeed->ctrl.threshold, (float)dev->ptrfeed->ctrl.num / (float)dev->ptrfeed->ctrl.den); if(mult != 1.0f || velocitydata->const_acceleration != 1.0f) { ApplySofteningAndConstantDeceleration(velocitydata, dx, dy, &fdx, &fdy, (mult > 1.0f) && soften); if (dx) { tmp = mult * fdx + dev->last.remainder[0]; /* Since it may not be apparent: lrintf() does not offer * strong statements about rounding; however because we * process each axis conditionally, there's no danger * of a toggling remainder. Its lack of guarantees likely * makes it faster on the average target. */ tmpi = lrintf(tmp); valuator_mask_set(val, 0, tmpi); dev->last.remainder[0] = tmp - (float)tmpi; } if (dy) { tmp = mult * fdy + dev->last.remainder[1]; tmpi = lrintf(tmp); valuator_mask_set(val, 1, tmpi); dev->last.remainder[1] = tmp - (float)tmpi; } DebugAccelF("pos (%i | %i) remainders x: %.3f y: %.3f delta x:%.3f y:%.3f\n", *px, *py, dev->last.remainder[0], dev->last.remainder[1], fdx, fdy); } } } /* remember last motion delta (for softening/slow movement treatment) */ velocitydata->last_dx = dx; velocitydata->last_dy = dy; }