static void *ac_flingthread(void *cookie){
  miui_debug("pthread %s start...\n", __FUNCTION__);
  AFLINGDATAP dt = (AFLINGDATAP) cookie;
  if (dt->ctl->win->isActived)
    dt->ctl->win->threadnum++;
  else{
    free(dt);
    return NULL;
  }
  int mz  = akinetic_fling(dt->akin);
  float vz=0.0;
  while ((mz!=0)&&(dt->ctl->win->isActived)){
    if (dt->ctl->forceNS) break;
    

    int zz=ceil(dt->akin->velocity);
    /*vz+=dt->akin->velocity-zz;
    if (abs(vz)>=1){
      if (vz<0){
        vz+=1.0;
        zz--;
      }
      else{
        vz-=1.0;
        zz++;
      }
    }*/
    //if (zz!=0){
      dt->scrollY[0]+=zz;
      dt->ctl->ondraw(dt->ctl);
      aw_draw(dt->ctl->win);
    //}
    
    if (!dt->ctl->win->isActived) break;
    if ((dt->scrollY[0]<0-(dt->ctl->h/4))||(dt->scrollY[0]>dt->maxScrollY+(dt->ctl->h/4))) break;
    if (ui_key_pressed(atmsg())){
      ACONTROLP nctl = (ACONTROLP) dt->ctl->win->controls[dt->ctl->win->touchIndex];
      if (nctl==dt->ctl)
        break;
    }
    //usleep(4000);
    
    if ((dt->scrollY[0]<0)||(dt->scrollY[0]>dt->maxScrollY))
      mz=akinetic_fling_dampered(dt->akin,0.6);
    else
      mz=akinetic_fling(dt->akin);
  }
  if (dt->ctl->win->isActived){
    if ((dt->scrollY[0]<0)||(dt->scrollY[0]>dt->maxScrollY)){
      ac_regbounce(dt->ctl,dt->scrollY,dt->maxScrollY);
    }
  }
  dt->ctl->win->threadnum--;
  free(dt);
  return NULL;
}
dword accheck_oninput(void * x,int action,ATEV * atev){
  ACONTROLP ctl= (ACONTROLP) x;
  ACCHECKDP d  = (ACCHECKDP) ctl->d;
  dword msg = 0;
  switch (action){
    case ATEV_MOUSEDN:
      {
        d->prevTouchY  = atev->y;
        akinetic_downhandler(&d->akin,atev->y);
        
        int touchpos = atev->y - ctl->y + d->scrollY;
        int i;
        for (i=0;i<d->itemn;i++){
          if ((touchpos>=d->items[i]->y)&&(touchpos<d->items[i]->y+d->items[i]->h)){
            ac_regpushwait(
              ctl,&d->prevTouchY,&d->invalidDrawItem,i
            );
            break;
          }
        }
      }
      break;
    case ATEV_MOUSEUP:
      {
        if ((d->prevTouchY!=-50)&&(abs(d->prevTouchY-atev->y)<agdp()*5)){
          d->prevTouchY=-50;
          int touchpos = atev->y - ctl->y + d->scrollY;
          
          int i;
          for (i=0;i<d->itemn;i++){
            if ((!d->items[i]->isTitle)&&(touchpos>=d->items[i]->y)&&(touchpos<d->items[i]->y+d->items[i]->h)){
              d->items[i]->checked = (d->items[i]->checked)?0:1;
              if ((d->touchedItem != -1)&&(d->touchedItem!=i)){
                int tmptouch=d->touchedItem;
                d->touchedItem = -1;
                accheck_redrawitem(ctl,tmptouch);
              }
              
              int prevfocus = d->focusedItem;
              d->focusedItem= i;
              d->touchedItem= i;
              if ((prevfocus!=-1)&&(prevfocus!=i)){
                accheck_redrawitem(ctl,prevfocus);
              }
              
              
              accheck_redrawitem(ctl,i);
              ctl->ondraw(ctl);
              aw_draw(ctl->win);
              vibrate(30);              
              break;
            }
          }
          
          if ((d->scrollY<0)||(d->scrollY>d->maxScrollY)){
            ac_regbounce(ctl,&d->scrollY,d->maxScrollY);
          }
        }
        else{
          if (akinetic_uphandler(&d->akin,atev->y)){
            ac_regfling(ctl,&d->akin,&d->scrollY,d->maxScrollY);
          }
          else if ((d->scrollY<0)||(d->scrollY>d->maxScrollY)){
            ac_regbounce(ctl,&d->scrollY,d->maxScrollY);
          }
        }
        if (d->touchedItem != -1){
          usleep(30);
          int tmptouch=d->touchedItem;
          d->touchedItem = -1;
          accheck_redrawitem(ctl,tmptouch);
          ctl->ondraw(ctl);
          msg=aw_msg(0,1,0,0);
        }
      }
      break;
    case ATEV_MOUSEMV:
      {
        byte allowscroll=1;
        if (atev->y!=0){
          if (d->prevTouchY!=-50){
            if (abs(d->prevTouchY-atev->y)>=agdp()*5){
              d->prevTouchY=-50;
              if (d->touchedItem != -1){
                int tmptouch=d->touchedItem;
                d->touchedItem = -1;
                accheck_redrawitem(ctl,tmptouch);
                ctl->ondraw(ctl);
                aw_draw(ctl->win);
              }
            }
            else
              allowscroll=0;
          }
          if (allowscroll){
            int mv = akinetic_movehandler(&d->akin,atev->y);
            if (mv!=0){
              if ((d->scrollY<0)&&(mv<0)){
                float dumpsz = 0.6-(0.6*(((float) abs(d->scrollY))/(ctl->h/4)));
                d->scrollY+=floor(mv*dumpsz);
              }
              else if ((d->scrollY>d->maxScrollY)&&(mv>0)){
                float dumpsz = 0.6-(0.6*(((float) abs(d->scrollY-d->maxScrollY))/(ctl->h/4)));
                d->scrollY+=floor(mv*dumpsz);
              }
              else
                d->scrollY+=mv;
  
              if (d->scrollY<0-(ctl->h/4)) d->scrollY=0-(ctl->h/4);
              if (d->scrollY>d->maxScrollY+(ctl->h/4)) d->scrollY=d->maxScrollY+(ctl->h/4);
              msg=aw_msg(0,1,0,0);
              ctl->ondraw(ctl);
            }
          }
        }
      }
      break;
      case ATEV_SELECT:
      {
        if ((d->focusedItem>-1)&&(d->draweditemn>0)){
          if (atev->d){
            if ((d->touchedItem != -1)&&(d->touchedItem!=d->focusedItem)){
              int tmptouch=d->touchedItem;
              d->touchedItem = -1;
              accheck_redrawitem(ctl,tmptouch);
            }
            vibrate(30);
            d->touchedItem=d->focusedItem;
            accheck_redrawitem(ctl,d->focusedItem);
            ctl->ondraw(ctl);
            msg=aw_msg(0,1,0,0);
          }
          else{
            if ((d->touchedItem != -1)&&(d->touchedItem!=d->focusedItem)){
              int tmptouch=d->touchedItem;
              d->touchedItem = -1;
              accheck_redrawitem(ctl,tmptouch);
            }
            d->items[d->focusedItem]->checked = (d->items[d->focusedItem]->checked)?0:1;
            d->touchedItem=-1;
            accheck_redrawitem(ctl,d->focusedItem);
            ctl->ondraw(ctl);
            msg=aw_msg(0,1,0,0);
          }
        }
      }
      break;
      case ATEV_DOWN:
        {
          if ((d->focusedItem<d->itemn-1)&&(d->draweditemn>0)){
            int prevfocus = d->focusedItem;
            d->focusedItem++;
            while(d->items[d->focusedItem]->isTitle){
              d->focusedItem++;
              if (d->focusedItem>d->itemn-1){
                d->focusedItem = prevfocus;
                return 0;
              }
            }
            accheck_redrawitem(ctl,prevfocus);
            accheck_redrawitem(ctl,d->focusedItem);
            ctl->ondraw(ctl);
            msg=aw_msg(0,1,1,0);
            
            int reqY = d->items[d->focusedItem]->y - round((ctl->h/2) - (d->items[d->focusedItem]->h/2));
            ac_regscrollto(
              ctl,
              &d->scrollY,
              d->maxScrollY,
              reqY,
              &d->focusedItem,
              d->focusedItem
            );
          }
        }
      break;
      case ATEV_UP:
        {
          if ((d->focusedItem>0)&&(d->draweditemn>0)){
            int prevfocus = d->focusedItem;
            d->focusedItem--;
            while(d->items[d->focusedItem]->isTitle){
              d->focusedItem--;
              if (d->focusedItem<0){
                d->focusedItem = prevfocus;
                return 0;
              }
            }
            accheck_redrawitem(ctl,prevfocus);
            accheck_redrawitem(ctl,d->focusedItem);
            ctl->ondraw(ctl);
            msg=aw_msg(0,1,1,0);
            
            int reqY = d->items[d->focusedItem]->y - round((ctl->h/2) - (d->items[d->focusedItem]->h/2));
            ac_regscrollto(
              ctl,
              &d->scrollY,
              d->maxScrollY,
              reqY,
              &d->focusedItem,
              d->focusedItem
            );
          }
        }
      break;
  }
  return msg;
}
dword actext_oninput(void * x,int action,ATEV * atev){
  ACONTROLP ctl= (ACONTROLP) x;
  ACTEXTDP  d  = (ACTEXTDP) ctl->d;
  if (d->maxScrollY==0) return 0;
  dword msg = 0;
  switch (action){
    case ATEV_MOUSEDN:
      {
        akinetic_downhandler(&d->akin,atev->y);
      }
      break;
    case ATEV_MOUSEUP:
      {
        if (akinetic_uphandler(&d->akin,atev->y))
          ac_regfling(ctl,&d->akin,&d->scrollY,d->maxScrollY);
        else if ((d->scrollY<0)||(d->scrollY>d->maxScrollY)){
          ac_regbounce(ctl,&d->scrollY,d->maxScrollY);
        }
      }
      break;
    case ATEV_MOUSEMV:
      {
        if (atev->y!=0){
          int mv = akinetic_movehandler(&d->akin,atev->y);
          if (mv!=0){
            if ((d->scrollY<0)&&(mv<0)){
              float dumpsz = 0.6-(0.6*(((float) abs(d->scrollY))/(ctl->h/4)));
              d->scrollY+=floor(mv*dumpsz);
            }
            else if ((d->scrollY>d->maxScrollY)&&(mv>0)){
              float dumpsz = 0.6-(0.6*(((float) abs(d->scrollY-d->maxScrollY))/(ctl->h/4)));
              d->scrollY+=floor(mv*dumpsz);
            }
            else
              d->scrollY+=mv;

            if (d->scrollY<0-(ctl->h/4)) d->scrollY=0-(ctl->h/4);
            if (d->scrollY>d->maxScrollY+(ctl->h/4)) d->scrollY=d->maxScrollY+(ctl->h/4);
            msg=aw_msg(0,1,0,0);
            ctl->ondraw(ctl);
          }
        }
      }
      break;
      case ATEV_DOWN:
        {
          if (d->scrollY<d->maxScrollY){
            msg=aw_msg(0,1,1,0);
            int reqY = d->scrollY+ceil(ctl->h/8);
            if (reqY>d->maxScrollY) reqY = d->maxScrollY;
            d->targetY=reqY;
            ac_regscrollto(
              ctl,
              &d->scrollY,
              d->maxScrollY,
              reqY,
              &d->targetY,
              d->targetY
            );
          }
        }
      break;
      case ATEV_UP:
        {
          if (d->scrollY>0){
            msg=aw_msg(0,1,1,0);
            int reqY = d->scrollY-ceil(ctl->h/8);
            if (reqY<0) reqY = 0;
            d->targetY=reqY;
            ac_regscrollto(
              ctl,
              &d->scrollY,
              d->maxScrollY,
              reqY,
              &d->targetY,
              d->targetY
            );
          }
        }
      break;
  }
  return msg;
}
dword afbox_oninput(void * x,int action,ATEV * atev){
  ACONTROLP ctl= (ACONTROLP) x;
  AFBOXDP d  = (AFBOXDP) ctl->d;
  dword msg = 0;
  switch (action){
    case 444:
      {
        // printf("HOLDED: %i - %s",d->touchedItem,d->items[d->touchedItem]->title);
        vibrate(30);
        int tmptouch=d->touchedItem;
        int tmpfocus=d->focusedItem;
        d->selectedId  = tmptouch;
        d->focusedItem = tmptouch;
        d->touchedItem = -1;
        if (tmpfocus!=tmptouch) afbox_redrawitem_ex(ctl,tmpfocus);
        afbox_redrawitem_ex(ctl,tmptouch);
        ctl->ondraw(ctl);
        msg=aw_msg(d->holdmsg,1,0,0);
        atouch_send_message(msg);
      }
      break;
    case ATEV_MOUSEDN:
      {
        d->prevTouchY  = atev->y;
        akinetic_downhandler(&d->akin,atev->y);
        
        int touchpos = atev->y - ctl->y + d->scrollY;
        int i;
        for (i=0;i<d->itemn;i++){
          if ((touchpos>=d->items[i]->y)&&(touchpos<d->items[i]->y+d->items[i]->h)){
            ac_regpushwait(
              ctl,&d->prevTouchY,&d->invalidDrawItem,i
            );
            break;
          }
        }
      }
      break;
    case ATEV_MOUSEUP:
      {
        byte is_holded = 0;
        if (d->lasttouch==-1) is_holded=1;
        d->lasttouch=0;
        byte ag_check_msg = 0;
        if ((d->prevTouchY!=-50)&&(abs(d->prevTouchY-atev->y)<agdp()*5)){
          d->prevTouchY=-50;
          int touchpos = atev->y - ctl->y + d->scrollY;
          
          byte oncheckpush=((d->check_n>0)||(atev->x>((ctl->x+ctl->w)-(agdp()*32))))?1:0;
          
          if (d->boxtype!=0) oncheckpush=0;
          
          int i;
          for (i=0;i<d->itemn;i++){
            if ((!d->items[i]->isTitle)&&(touchpos>=d->items[i]->y)&&(touchpos<d->items[i]->y+d->items[i]->h)){
              
              if ((oncheckpush)&&(!is_holded)){
                d->items[i]->checked = (d->items[i]->checked)?0:1;
                if (d->items[i]->checked)
                  d->check_n++;
                else
                  d->check_n--;
                ag_check_msg = d->changemsg;
              }
              
              if ((d->touchedItem != -1)&&(d->touchedItem!=i)){
                int tmptouch=d->touchedItem;
                d->touchedItem = -1;
                afbox_redrawitem_ex(ctl,tmptouch);
              }
              
              int prevfocus = d->focusedItem;
              d->focusedItem= i;
              d->touchedItem= i;
              if ((prevfocus!=-1)&&(prevfocus!=i)){
                afbox_redrawitem_ex(ctl,prevfocus);
              }
              
              
              afbox_redrawitem_ex(ctl,i);
              ctl->ondraw(ctl);
              aw_draw(ctl->win);
              
              if (!is_holded){
                vibrate(30);
                
                if (!oncheckpush){
                  ag_check_msg = d->touchmsg;
                  d->selectedId=i;
                  msg=aw_msg(ag_check_msg,1,0,0);
                }
              }
              break;
            }
          }
          if ((d->scrollY<0)||(d->scrollY>d->maxScrollY)){
            ac_regbounce(ctl,&d->scrollY,d->maxScrollY);
          }
        }
        else{
          if (akinetic_uphandler(&d->akin,atev->y)){
            ac_regfling(ctl,&d->akin,&d->scrollY,d->maxScrollY);
          }
          else if ((d->scrollY<0)||(d->scrollY>d->maxScrollY)){
            ac_regbounce(ctl,&d->scrollY,d->maxScrollY);
          }
        }
        if (d->touchedItem != -1){
          usleep(30);
          int tmptouch=d->touchedItem;
          d->touchedItem = -1;
          afbox_redrawitem_ex(ctl,tmptouch);
          ctl->ondraw(ctl);
          msg=aw_msg(ag_check_msg,1,0,0);
        }
      }
      break;
    case ATEV_MOUSEMV:
      {
        byte allowscroll=1;
        if (atev->y!=0){
          if (d->prevTouchY!=-50){
            if (abs(d->prevTouchY-atev->y)>=agdp()*5){
              d->prevTouchY=-50;
              if (d->touchedItem != -1){
                int tmptouch=d->touchedItem;
                d->touchedItem = -1;
                afbox_redrawitem_ex(ctl,tmptouch);
                ctl->ondraw(ctl);
                aw_draw(ctl->win);
              }
            }
            else
              allowscroll=0;
          }
          if (allowscroll){
            d->lasttouch=0;
            int mv = akinetic_movehandler(&d->akin,atev->y);
            if (mv!=0){
              if ((d->scrollY<0)&&(mv<0)){
                float dumpsz = 0.6-(0.6*(((float) abs(d->scrollY))/(ctl->h/4)));
                d->scrollY+=floor(mv*dumpsz);
              }
              else if ((d->scrollY>d->maxScrollY)&&(mv>0)){
                float dumpsz = 0.6-(0.6*(((float) abs(d->scrollY-d->maxScrollY))/(ctl->h/4)));
                d->scrollY+=floor(mv*dumpsz);
              }
              else
                d->scrollY+=mv;
  
              if (d->scrollY<0-(ctl->h/4)) d->scrollY=0-(ctl->h/4);
              if (d->scrollY>d->maxScrollY+(ctl->h/4)) d->scrollY=d->maxScrollY+(ctl->h/4);
              msg=aw_msg(0,1,0,0);
              ctl->ondraw(ctl);
            }
          }
        }
      }
      break;
      case ATEV_SEARCH:
      {
        d->lasttouch=0;
        if (d->boxtype==0){
          if ((d->focusedItem>-1)&&(d->draweditemn>0)){
            if (atev->d){
              if ((d->touchedItem != -1)&&(d->touchedItem!=d->focusedItem)){
                int tmptouch=d->touchedItem;
                d->touchedItem = -1;
                afbox_redrawitem_ex(ctl,tmptouch);
              }
              vibrate(30);
              d->touchedItem=d->focusedItem;
              afbox_redrawitem_ex(ctl,d->focusedItem);
              ctl->ondraw(ctl);
              msg=aw_msg(0,1,0,0);
            }
            else{
              d->items[d->focusedItem]->checked = (d->items[d->focusedItem]->checked)?0:1;
              if (d->items[d->focusedItem]->checked)
                d->check_n++;
              else
                d->check_n--;
              d->touchedItem=-1;
              afbox_redrawitem_ex(ctl,d->focusedItem);
              ctl->ondraw(ctl);
              msg=aw_msg(d->changemsg,1,0,0);
            }
          }
        }
      }
      break;
      case ATEV_SELECT:
        {
          d->lasttouch=0;
          if ((d->focusedItem>-1)&&(d->draweditemn>0)){
            if (atev->d){
              if ((d->touchedItem != -1)&&(d->touchedItem!=d->focusedItem)){
                int tmptouch=d->touchedItem;
                d->touchedItem = -1;
                afbox_redrawitem_ex(ctl,tmptouch);
              }
              vibrate(30);
              d->touchedItem=d->focusedItem;
              afbox_redrawitem_ex(ctl,d->focusedItem);
              ctl->ondraw(ctl);
              msg=aw_msg(0,1,0,0);
            }
            else{
              if ((d->check_n>0)&&(d->boxtype==0)){
                d->items[d->focusedItem]->checked = (d->items[d->focusedItem]->checked)?0:1;
                if (d->items[d->focusedItem]->checked)
                  d->check_n++;
                else
                  d->check_n--;
                d->touchedItem=-1;
                afbox_redrawitem_ex(ctl,d->focusedItem);
                ctl->ondraw(ctl);
                msg=aw_msg(d->changemsg,1,0,0);
              }
              else{
                if ((d->touchedItem != -1)&&(d->touchedItem!=d->focusedItem)){
                  int tmptouch=d->touchedItem;
                  d->touchedItem = -1;
                  afbox_redrawitem_ex(ctl,tmptouch);
                }
                d->selectedId=d->focusedItem;
                d->touchedItem=-1;
                afbox_redrawitem_ex(ctl,d->focusedItem);
                ctl->ondraw(ctl);
                msg=aw_msg(d->touchmsg,1,0,0);
              }
            }
          }
        }
        break;
      case ATEV_DOWN:
        {
          d->lasttouch=0;
          if ((d->focusedItem<d->itemn-1)&&(d->draweditemn>0)){
            int prevfocus = d->focusedItem;
            d->focusedItem++;
            while(d->items[d->focusedItem]->isTitle){
              d->focusedItem++;
              if (d->focusedItem>d->itemn-1){
                d->focusedItem = prevfocus;
                d->selectedId  = d->focusedItem;
                return 0;
              }
            }
            d->selectedId  = d->focusedItem;
            afbox_redrawitem_ex(ctl,prevfocus);
            afbox_redrawitem_ex(ctl,d->focusedItem);
            ctl->ondraw(ctl);
            msg=aw_msg(0,1,1,0);
            
            int reqY = d->items[d->focusedItem]->y - round((ctl->h/2) - (d->items[d->focusedItem]->h/2));
            ac_regscrollto(
              ctl,
              &d->scrollY,
              d->maxScrollY,
              reqY,
              &d->focusedItem,
              d->focusedItem
            );
          }
        }
      break;
      case ATEV_UP:
        {
          d->lasttouch=0;
          if ((d->focusedItem>0)&&(d->draweditemn>0)){
            int prevfocus = d->focusedItem;
            d->focusedItem--;
            while(d->items[d->focusedItem]->isTitle){
              d->focusedItem--;
              if (d->focusedItem<0){
                d->focusedItem = prevfocus;
                d->selectedId  = d->focusedItem;
                return 0;
              }
            }
            d->selectedId  = d->focusedItem;
            afbox_redrawitem_ex(ctl,prevfocus);
            afbox_redrawitem_ex(ctl,d->focusedItem);
            ctl->ondraw(ctl);
            msg=aw_msg(0,1,1,0);
            
            int reqY = d->items[d->focusedItem]->y - round((ctl->h/2) - (d->items[d->focusedItem]->h/2));
            ac_regscrollto(
              ctl,
              &d->scrollY,
              d->maxScrollY,
              reqY,
              &d->focusedItem,
              d->focusedItem
            );
          }
        }
      break;
  }
  return msg;
}