fix velocitytracker,noe numberpicker can fling happy:)

This commit is contained in:
houzh 2023-04-13 10:45:33 +00:00
parent 784e675587
commit 3d4c621089
7 changed files with 28 additions and 33 deletions

View File

@ -76,4 +76,4 @@ if (FONTCONFIG_LIBRARIES AND FONTCONFIG_INCLUDE_DIRS)
set(FONTCONFIG_INCLUDE_DIR ${FONTCONFIG_INCLUDE_DIRS}) set(FONTCONFIG_INCLUDE_DIR ${FONTCONFIG_INCLUDE_DIRS})
mark_as_advanced(FONTCONFIG_LIBRARIES FONTCONFIG_LIBRARY FONTCONFIG_INCLUDE_DIR FONTCONFIG_INCLUDE_DIRS) mark_as_advanced(FONTCONFIG_LIBRARIES FONTCONFIG_LIBRARY FONTCONFIG_INCLUDE_DIR FONTCONFIG_INCLUDE_DIRS)
endif (FONTCONFIG_LIBRARIES AND FONTCONFIG_INCLUDE_DIR) endif()

View File

@ -46,7 +46,7 @@ InputDevice::InputDevice(int fdev):listener(nullptr){
const INPUTAXISINFO*axis=devInfos.axis+j; const INPUTAXISINFO*axis=devInfos.axis+j;
if(axis->maximum!=axis->minimum) if(axis->maximum!=axis->minimum)
mDeviceInfo.addMotionRange(axis->axis,0/*source*/,axis->minimum,axis->maximum,axis->flat,axis->fuzz,axis->resolution); mDeviceInfo.addMotionRange(axis->axis,0/*source*/,axis->minimum,axis->maximum,axis->flat,axis->fuzz,axis->resolution);
LOGI_IF(axis->maximum!=axis->minimum,"axis[%d] range=%d,%d",axis->axis,axis->minimum,axis->maximum); LOGI_IF(axis->maximum!=axis->minimum,"devfd=%d axis[%d] range=%d,%d",fdev,axis->axis,axis->minimum,axis->maximum);
} }
// See if this is a keyboard. Ignore everything in the button range except for // See if this is a keyboard. Ignore everything in the button range except for
@ -213,7 +213,7 @@ int KeyDevice::putRawEvent(const struct timeval&tv,int type,int code,int value){
mRepeatCount=0; mRepeatCount=0;
mEvent.initialize(getId(),getSource(),(value?KeyEvent::ACTION_DOWN:KeyEvent::ACTION_UP)/*action*/,flags, mEvent.initialize(getId(),getSource(),(value?KeyEvent::ACTION_DOWN:KeyEvent::ACTION_UP)/*action*/,flags,
keycode,code/*scancode*/,0/*metaState*/,mRepeatCount, mDownTime,SystemClock::uptimeNanos()/*eventtime*/); keycode,code/*scancode*/,0/*metaState*/,mRepeatCount, mDownTime,SystemClock::uptimeMicros()/*eventtime*/);
LOGV("fd[%d] keycode:%08x->%04x[%s] action=%d flags=%d",getId(),code,keycode, mEvent.getLabel(),value,flags); LOGV("fd[%d] keycode:%08x->%04x[%s] action=%d flags=%d",getId(),code,keycode, mEvent.getLabel(),value,flags);
if(listener)listener(mEvent); if(listener)listener(mEvent);
break; break;
@ -309,10 +309,10 @@ int TouchDevice::putRawEvent(const struct timeval&tv,int type,int code,int value
mEvent.setActionButton(MotionEvent::BUTTON_PRIMARY); mEvent.setActionButton(MotionEvent::BUTTON_PRIMARY);
mEvent.setAction(value?MotionEvent::ACTION_DOWN:MotionEvent::ACTION_UP); mEvent.setAction(value?MotionEvent::ACTION_DOWN:MotionEvent::ACTION_UP);
if(value){ if(value){
mMoveTime = mDownTime =tv.tv_sec*1000+tv.tv_usec/1000; mMoveTime = mDownTime =tv.tv_sec*1000000+tv.tv_usec;
mEvent.setButtonState(MotionEvent::BUTTON_PRIMARY); mEvent.setButtonState(MotionEvent::BUTTON_PRIMARY);
}else{ }else{
mMoveTime =tv.tv_sec*1000+tv.tv_usec/1000; mMoveTime =tv.tv_sec*1000000+tv.tv_usec;;
mEvent.setButtonState(mEvent.getButtonState()&(~MotionEvent::BUTTON_PRIMARY)); mEvent.setButtonState(mEvent.getButtonState()&(~MotionEvent::BUTTON_PRIMARY));
} }
break; break;
@ -329,7 +329,7 @@ int TouchDevice::putRawEvent(const struct timeval&tv,int type,int code,int value
case EV_ABS: case EV_ABS:
switch(code){ switch(code){
case ABS_X ... ABS_Z : case ABS_X ... ABS_Z :
mMoveTime =tv.tv_sec*1000+tv.tv_usec/1000; mMoveTime =tv.tv_sec*1000000+tv.tv_usec;
setAxisValue(0,code,value,false) ; break; setAxisValue(0,code,value,false) ; break;
//case ABS_PRESSURE : setAxisValue(0,code,value,false) ; break; //case ABS_PRESSURE : setAxisValue(0,code,value,false) ; break;
case ABS_MT_SLOT : mPointSlot=value ; break; case ABS_MT_SLOT : mPointSlot=value ; break;
@ -354,6 +354,7 @@ int TouchDevice::putRawEvent(const struct timeval&tv,int type,int code,int value
switch(code){ switch(code){
case SYN_REPORT: case SYN_REPORT:
case SYN_MT_REPORT: case SYN_MT_REPORT:
mMoveTime =(tv.tv_sec*1000000+tv.tv_usec);
LOGV("%s pos=%.f,%.f",MotionEvent::actionToString(mEvent.getAction()).c_str(), LOGV("%s pos=%.f,%.f",MotionEvent::actionToString(mEvent.getAction()).c_str(),
mPointMAP.begin()->second.coord.getX(),mPointMAP.begin()->second.coord.getY() ); mPointMAP.begin()->second.coord.getX(),mPointMAP.begin()->second.coord.getY() );
mEvent.initialize(getId(),getSource(),mEvent.getAction(),mEvent.getActionButton(), mEvent.initialize(getId(),getSource(),mEvent.getAction(),mEvent.getActionButton(),

View File

@ -12,7 +12,7 @@ namespace cdroid{
// stopped. We need to detect this case so that we can accurately predict the // stopped. We need to detect this case so that we can accurately predict the
// velocity after the pointer starts moving again. // velocity after the pointer starts moving again.
static const nsecs_t ASSUME_POINTER_STOPPED_TIME = 40;/*Millisecond*/ static const nsecs_t ASSUME_POINTER_STOPPED_TIME = 40*1000;/*Millisecond*/
static float vectorDot(const float* a, const float* b, uint32_t m) { static float vectorDot(const float* a, const float* b, uint32_t m) {
float r = 0; float r = 0;
@ -411,14 +411,14 @@ void IntegratingVelocityTrackerStrategy::initState(State& state,
void IntegratingVelocityTrackerStrategy::updateState(State& state, void IntegratingVelocityTrackerStrategy::updateState(State& state,
nsecs_t eventTime, float xpos, float ypos) const { nsecs_t eventTime, float xpos, float ypos) const {
const nsecs_t MIN_TIME_DELTA = 2 ; const nsecs_t MIN_TIME_DELTA = 2*1000 ;
const float FILTER_TIME_CONSTANT = 0.010f; // 10 milliseconds const float FILTER_TIME_CONSTANT = 0.010f; // 10 milliseconds
if (eventTime <= state.updateTime + MIN_TIME_DELTA) { if (eventTime <= state.updateTime + MIN_TIME_DELTA) {
return; return;
} }
float dt = (eventTime - state.updateTime) *0.001f;//0.000000001f; float dt = (eventTime - state.updateTime) *0.000001f;//0.000000001f;
state.updateTime = eventTime; state.updateTime = eventTime;
float xvel = (xpos - state.xpos) / dt; float xvel = (xpos - state.xpos) / dt;
@ -507,7 +507,7 @@ static float kineticEnergyToVelocity(float work) {
static float calculateImpulseVelocity(const nsecs_t* t, const float* x, size_t count) { static float calculateImpulseVelocity(const nsecs_t* t, const float* x, size_t count) {
// The input should be in reversed time order (most recent sample at index i=0) // The input should be in reversed time order (most recent sample at index i=0)
// t[i] is in nanoseconds, but due to FP arithmetic, convert to seconds inside this function // t[i] is in nanoseconds, but due to FP arithmetic, convert to seconds inside this function
static constexpr float SECONDS_PER_NANO = 1E-3;//android use nanosecond used value 1E-9; static constexpr float SECONDS_PER_MICRO = 1E-6;//android use nanosecond used value 1E-9;
if (count < 2) { if (count < 2) {
return 0; // if 0 or 1 points, velocity is zero return 0; // if 0 or 1 points, velocity is zero
@ -520,7 +520,7 @@ static float calculateImpulseVelocity(const nsecs_t* t, const float* x, size_t c
LOGE("Events have identical time stamps t=%lld, setting velocity = 0", t[0]); LOGE("Events have identical time stamps t=%lld, setting velocity = 0", t[0]);
return 0; return 0;
} }
return (x[1] - x[0]) / (SECONDS_PER_NANO * (t[1] - t[0])); return (x[1] - x[0]) / (SECONDS_PER_MICRO * (t[1] - t[0]));
} }
// Guaranteed to have at least 3 points here // Guaranteed to have at least 3 points here
float work = 0; float work = 0;
@ -530,7 +530,7 @@ static float calculateImpulseVelocity(const nsecs_t* t, const float* x, size_t c
continue; continue;
} }
float vprev = kineticEnergyToVelocity(work); // v[i-1] float vprev = kineticEnergyToVelocity(work); // v[i-1]
float vcurr = (x[i] - x[i-1]) / (SECONDS_PER_NANO * (t[i] - t[i-1])); // v[i] float vcurr = (x[i] - x[i-1]) / (SECONDS_PER_MICRO * (t[i] - t[i-1])); // v[i]
work += (vcurr - vprev) * fabsf(vcurr); work += (vcurr - vprev) * fabsf(vcurr);
if (i == count - 1) { if (i == count - 1) {
work *= 0.5; // initial condition, case 2) above work *= 0.5; // initial condition, case 2) above
@ -544,16 +544,16 @@ bool ImpulseVelocityTrackerStrategy::getEstimator(uint32_t id,
outEstimator->clear(); outEstimator->clear();
// Iterate over movement samples in reverse time order and collect samples. // Iterate over movement samples in reverse time order and collect samples.
float x[HISTORY_SIZE]; float x[HISTORY_SIZE]={.0f};
float y[HISTORY_SIZE]; float y[HISTORY_SIZE]={.0f};
nsecs_t time[HISTORY_SIZE]; nsecs_t time[HISTORY_SIZE]={0};
size_t m = 0; // number of points that will be used for fitting size_t m = 0; // number of points that will be used for fitting
size_t index = mIndex; size_t index = mIndex;
const Movement& newestMovement = mMovements[mIndex]; const Movement& newestMovement = mMovements[mIndex];
do { do {
const Movement& movement = mMovements[index]; const Movement& movement = mMovements[index];
if (!movement.idBits.hasBit(id)) { if (!movement.idBits.hasBit(id)) {
break; LOGD("hasbit(%d)failed",id);break;
} }
nsecs_t age = newestMovement.eventTime - movement.eventTime; nsecs_t age = newestMovement.eventTime - movement.eventTime;
@ -808,7 +808,7 @@ bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id,
x[m] = position.x; x[m] = position.x;
y[m] = position.y; y[m] = position.y;
w[m] = chooseWeight(index); w[m] = chooseWeight(index);
time[m] = -age * 0.001f;//android nanosecond use 0.000000001f; time[m] = -age * 0.000001f;//android nanosecond use 0.000000001f;
index = (index == 0 ? HISTORY_SIZE : index) - 1; index = (index == 0 ? HISTORY_SIZE : index) - 1;
} while (++m < HISTORY_SIZE); } while (++m < HISTORY_SIZE);
@ -873,7 +873,7 @@ float LeastSquaresVelocityTrackerStrategy::chooseWeight(uint32_t index) const {
uint32_t nextIndex = (index + 1) % HISTORY_SIZE; uint32_t nextIndex = (index + 1) % HISTORY_SIZE;
float deltaMillis = (mMovements[nextIndex].eventTime- mMovements[index].eventTime) float deltaMillis = (mMovements[nextIndex].eventTime- mMovements[index].eventTime)
* 0.000001f; *0.001f;/*cdroid use us android usens 0.000001f*/;
if (deltaMillis < 0 ) return 0.5f; if (deltaMillis < 0 ) return 0.5f;
if (deltaMillis < 10) return 0.5f + deltaMillis * 0.05; if (deltaMillis < 10) return 0.5f + deltaMillis * 0.05;
return 1.0f; return 1.0f;
@ -885,7 +885,7 @@ float LeastSquaresVelocityTrackerStrategy::chooseWeight(uint32_t index) const {
// age 10ms: 1.0 // age 10ms: 1.0
// age 50ms: 1.0 // age 50ms: 1.0
// age 60ms: 0.5 // age 60ms: 0.5
float ageMillis = (mMovements[mIndex].eventTime - mMovements[index].eventTime) * 0.000001f; float ageMillis = (mMovements[mIndex].eventTime - mMovements[index].eventTime) * 0.001f;/*android us ns 0.000001f*/;
if (ageMillis < 0 ) return 0.5f; if (ageMillis < 0 ) return 0.5f;
if (ageMillis < 10) return 0.5f + ageMillis * 0.05; if (ageMillis < 10) return 0.5f + ageMillis * 0.05;
if (ageMillis < 50) return 1.0f; if (ageMillis < 50) return 1.0f;
@ -897,7 +897,7 @@ float LeastSquaresVelocityTrackerStrategy::chooseWeight(uint32_t index) const {
// Weight points based on their age, weighing older points less. // Weight points based on their age, weighing older points less.
// age 0ms: 1.0 , age 50ms: 1.0 , age 100ms: 0.5 // age 0ms: 1.0 , age 50ms: 1.0 , age 100ms: 0.5
float ageMillis = (mMovements[mIndex].eventTime - mMovements[index].eventTime) float ageMillis = (mMovements[mIndex].eventTime - mMovements[index].eventTime)
* 0.000001f; *0.001f;/*android use ns 0.000001f*/;
if (ageMillis < 50) { if (ageMillis < 50) {
return 1.0f; return 1.0f;
} }
@ -934,7 +934,6 @@ void VelocityTracker::clear() {
void VelocityTracker::addMovement(const MotionEvent& event) { void VelocityTracker::addMovement(const MotionEvent& event) {
mVelocityTracker->addMovement(event); mVelocityTracker->addMovement(event);
LOGV("%f,%f",event.getX(),event.getY());
} }
void VelocityTracker::computeCurrentVelocity(int32_t units){ void VelocityTracker::computeCurrentVelocity(int32_t units){

View File

@ -139,7 +139,7 @@ private:
// Sample horizon. // Sample horizon.
// We don't use too much history by default since we want to react to quick // We don't use too much history by default since we want to react to quick
// changes in direction. // changes in direction.
static const nsecs_t HORIZON = 100; //Millisecond static const nsecs_t HORIZON = 100000; //Millisecond
// Number of samples to keep. // Number of samples to keep.
static const uint32_t HISTORY_SIZE = 20; static const uint32_t HISTORY_SIZE = 20;
struct Movement { struct Movement {
@ -174,7 +174,7 @@ private:
// Sample horizon. // Sample horizon.
// We don't use too much history by default since we want to react to quick // We don't use too much history by default since we want to react to quick
// changes in direction. // changes in direction.
static constexpr nsecs_t HORIZON = 100; //Millisecond static constexpr nsecs_t HORIZON = 100000; //Millisecond
// Number of samples to keep. // Number of samples to keep.
static constexpr size_t HISTORY_SIZE = 20; static constexpr size_t HISTORY_SIZE = 20;

View File

@ -316,9 +316,8 @@ bool NumberPicker::onTouchEvent(MotionEvent& event){
removeBeginSoftInputCommand(); removeBeginSoftInputCommand();
removeChangeCurrentByOneFromLongPress(); removeChangeCurrentByOneFromLongPress();
pshCancel();//mPressedStateHelper.cancel(); pshCancel();//mPressedStateHelper.cancel();
//VelocityTracker* velocityTracker = mVelocityTracker;
mVelocityTracker->computeCurrentVelocity(1000, mMaximumFlingVelocity); mVelocityTracker->computeCurrentVelocity(1000, mMaximumFlingVelocity);
int initialVelocity = (int) mVelocityTracker->getYVelocity(); const int initialVelocity = (int) mVelocityTracker->getYVelocity();
if (std::abs(initialVelocity) > mMinimumFlingVelocity) { if (std::abs(initialVelocity) > mMinimumFlingVelocity) {
fling(initialVelocity); fling(initialVelocity);
onScrollStateChange(OnScrollListener::SCROLL_STATE_FLING); onScrollStateChange(OnScrollListener::SCROLL_STATE_FLING);

View File

@ -168,20 +168,18 @@ INT InputGetEvents(INPUTEVENT*outevents,UINT max,DWORD timeout){
return E_ERROR; return E_ERROR;
} }
for(int i=0;i<dev.nfd;i++){ for(int i=0;i<dev.nfd;i++){
struct timespec ts;
if(!FD_ISSET(dev.fds[i],&rfds))continue; if(!FD_ISSET(dev.fds[i],&rfds))continue;
if(dev.fds[i]!=dev.pipe[0]){ if(dev.fds[i]!=dev.pipe[0]){
clock_gettime(CLOCK_MONOTONIC,&ts);
rc=read(dev.fds[i],events, sizeof(events)/sizeof(struct input_event)); rc=read(dev.fds[i],events, sizeof(events)/sizeof(struct input_event));
for(int j=0;j<rc/sizeof(struct input_event)&&(count<max);j++,e++,count++){ for(int j=0;j<rc/sizeof(struct input_event)&&(count<max);j++,e++,count++){
e->tv_sec =ts.tv_sec;//events[j].time.tv_sec; e->tv_sec = events[j].time.tv_sec;
e->tv_usec=ts.tv_nsec/10000+j*100;//events[j].time.tv_usec; e->tv_usec= events[j].time.tv_usec;
e->type = events[j].type; e->type = events[j].type;
e->code = events[j].code; e->code = events[j].code;
e->value= events[j].value; e->value= events[j].value;
e->device=dev.fds[i]; e->device=dev.fds[i];
LOGV_IF(e->type<EV_SW,"fd:%d [%s]%02x,%02x,%02x time=%ld.%ld",dev.fds[i], LOGV_IF(e->type<EV_SW,"fd:%d [%s]%02x,%02x,%02x time=%ld.%ld time2=%ld.%ld",dev.fds[i],
type2name[e->type],e->type,e->code,e->value,e->tv_sec,e->tv_usec); type2name[e->type],e->type,e->code,e->value,e->tv_sec,e->tv_usec,events[j].time.tv_sec,events[j].time.tv_usec);
} }
}else{//for pipe }else{//for pipe
rc=read(dev.fds[i],e, (max-count)*sizeof(INPUTEVENT)); rc=read(dev.fds[i],e, (max-count)*sizeof(INPUTEVENT));

View File

@ -168,10 +168,8 @@ INT InputGetEvents(INPUTEVENT*outevents,UINT max,DWORD timeout){
return E_ERROR; return E_ERROR;
} }
for(int i=0;i<dev.nfd;i++){ for(int i=0;i<dev.nfd;i++){
struct timespec ts;
if(!FD_ISSET(dev.fds[i],&rfds))continue; if(!FD_ISSET(dev.fds[i],&rfds))continue;
if(dev.fds[i]!=dev.pipe[0]){ if(dev.fds[i]!=dev.pipe[0]){
clock_gettime(CLOCK_MONOTONIC,&ts);
rc=read(dev.fds[i],events, sizeof(events)/sizeof(struct input_event)); rc=read(dev.fds[i],events, sizeof(events)/sizeof(struct input_event));
for(int j=0;j<rc/sizeof(struct input_event)&&(count<max);j++,e++,count++){ for(int j=0;j<rc/sizeof(struct input_event)&&(count<max);j++,e++,count++){
e->tv_sec =events[j].time.tv_sec; e->tv_sec =events[j].time.tv_sec;