First pass at Windows multi-touch gesture support
authorSam Lantinga <slouken@libsdl.org>
Tue, 30 Nov 2010 17:58:51 -0800
changeset 4919716b2cbf4c9e
parent 4918 f5f70fed2c4c
child 4920 a4032241deb5
First pass at Windows multi-touch gesture support
src/events/SDL_gesture.c
src/events/SDL_touch.c
src/video/win32/SDL_win32events.c
src/video/win32/SDL_win32video.c
src/video/win32/SDL_win32video.h
src/video/win32/SDL_win32window.c
     1.1 --- a/src/events/SDL_gesture.c	Tue Nov 30 12:38:46 2010 -0800
     1.2 +++ b/src/events/SDL_gesture.c	Tue Nov 30 17:58:51 2010 -0800
     1.3 @@ -97,7 +97,7 @@
     1.4      if((touchId < 0) || (SDL_gestureTouch[i].id == touchId)) {
     1.5        SDL_gestureTouch[i].recording = SDL_TRUE;
     1.6        if(touchId >= 0)
     1.7 -	return 1;
     1.8 +        return 1;
     1.9      }      
    1.10    }
    1.11    return (touchId < 0);
    1.12 @@ -122,7 +122,7 @@
    1.13    //if(SDL_RWops.write(src,&(templ->hash),sizeof(templ->hash),1) != 1) return 0;
    1.14    
    1.15    if(SDL_RWwrite(src,templ->path,
    1.16 -		 sizeof(templ->path[0]),DOLLARNPOINTS) != DOLLARNPOINTS) 
    1.17 +                 sizeof(templ->path[0]),DOLLARNPOINTS) != DOLLARNPOINTS) 
    1.18      return 0;
    1.19  
    1.20    return 1;
    1.21 @@ -134,7 +134,7 @@
    1.22    for(i = 0; i < SDL_numGestureTouches; i++) {
    1.23      SDL_GestureTouch* touch = &SDL_gestureTouch[i];
    1.24      for(j = 0;j < touch->numDollarTemplates; j++) {
    1.25 -	rtrn += SaveTemplate(&touch->dollarTemplate[i],src);
    1.26 +        rtrn += SaveTemplate(&touch->dollarTemplate[i],src);
    1.27      }
    1.28    }
    1.29    return rtrn;  
    1.30 @@ -146,7 +146,7 @@
    1.31      SDL_GestureTouch* touch = &SDL_gestureTouch[i];
    1.32      for(j = 0;j < touch->numDollarTemplates; j++) {
    1.33        if(touch->dollarTemplate[i].hash == gestureId) {
    1.34 -	return SaveTemplate(&touch->dollarTemplate[i],src);
    1.35 +        return SaveTemplate(&touch->dollarTemplate[i],src);
    1.36        }
    1.37      }
    1.38    }
    1.39 @@ -166,18 +166,18 @@
    1.40        inTouch = &SDL_gestureTouch[i];
    1.41  
    1.42      dollarTemplate = 
    1.43 -	(SDL_DollarTemplate *)SDL_realloc(inTouch->dollarTemplate,
    1.44 -		    (inTouch->numDollarTemplates + 1) * 
    1.45 -		    sizeof(SDL_DollarTemplate));
    1.46 +        (SDL_DollarTemplate *)SDL_realloc(inTouch->dollarTemplate,
    1.47 +                    (inTouch->numDollarTemplates + 1) * 
    1.48 +                    sizeof(SDL_DollarTemplate));
    1.49        if(!dollarTemplate) {
    1.50 -	SDL_OutOfMemory();
    1.51 -	return -1;
    1.52 +        SDL_OutOfMemory();
    1.53 +        return -1;
    1.54        }
    1.55 -	
    1.56 +        
    1.57        inTouch->dollarTemplate = dollarTemplate;
    1.58  
    1.59      templ = 
    1.60 -	&inTouch->dollarTemplate[inTouch->numDollarTemplates];
    1.61 +        &inTouch->dollarTemplate[inTouch->numDollarTemplates];
    1.62        SDL_memcpy(templ->path,path,DOLLARNPOINTS*sizeof(SDL_FloatPoint));
    1.63        templ->hash = SDL_HashDollar(templ->path);
    1.64        inTouch->numDollarTemplates++;    
    1.65 @@ -186,8 +186,8 @@
    1.66    } else {
    1.67      SDL_DollarTemplate* dollarTemplate = 
    1.68        ( SDL_DollarTemplate *)SDL_realloc(inTouch->dollarTemplate,
    1.69 -		  (inTouch->numDollarTemplates + 1) * 
    1.70 -		  sizeof(SDL_DollarTemplate));
    1.71 +                  (inTouch->numDollarTemplates + 1) * 
    1.72 +                  sizeof(SDL_DollarTemplate));
    1.73      if(!dollarTemplate) {
    1.74        SDL_OutOfMemory();
    1.75        return -1;
    1.76 @@ -212,7 +212,7 @@
    1.77    if(touchId >= 0) {
    1.78      for(i = 0;i < SDL_numGestureTouches; i++)
    1.79        if(SDL_gestureTouch[i].id == touchId)
    1.80 -	touch = &SDL_gestureTouch[i];
    1.81 +        touch = &SDL_gestureTouch[i];
    1.82      if(touch == NULL) return -1;
    1.83    }
    1.84  
    1.85 @@ -229,10 +229,10 @@
    1.86      else {
    1.87        //printf("Adding to: %i touches\n",SDL_numGestureTouches);
    1.88        for(i = 0;i < SDL_numGestureTouches; i++) {
    1.89 -	touch = &SDL_gestureTouch[i];
    1.90 -	//printf("Adding loaded gesture to + touches\n");
    1.91 -	//TODO: What if this fails?
    1.92 -	SDL_AddDollarGesture(touch,templ.path);	
    1.93 +        touch = &SDL_gestureTouch[i];
    1.94 +        //printf("Adding loaded gesture to + touches\n");
    1.95 +        //TODO: What if this fails?
    1.96 +        SDL_AddDollarGesture(touch,templ.path);        
    1.97        }
    1.98        loaded++;
    1.99      }
   1.100 @@ -251,7 +251,7 @@
   1.101      p.x = (float)(points[i].x * SDL_cos(ang) - points[i].y * SDL_sin(ang));
   1.102      p.y = (float)(points[i].x * SDL_sin(ang) + points[i].y * SDL_cos(ang));
   1.103      dist += (float)(SDL_sqrt((p.x-templ[i].x)*(p.x-templ[i].x)+
   1.104 -		 (p.y-templ[i].y)*(p.y-templ[i].y)));
   1.105 +                 (p.y-templ[i].y)*(p.y-templ[i].y)));
   1.106    }
   1.107    return dist/DOLLARNPOINTS;
   1.108    
   1.109 @@ -308,9 +308,9 @@
   1.110    if(path.length <= 0) {
   1.111      for(i=1;i<path.numPoints;i++) {
   1.112        float dx = path.p[i  ].x - 
   1.113 -	         path.p[i-1].x;
   1.114 +                 path.p[i-1].x;
   1.115        float dy = path.p[i  ].y - 
   1.116 -	         path.p[i-1].y;
   1.117 +                 path.p[i-1].y;
   1.118        path.length += (float)(SDL_sqrt(dx*dx+dy*dy));
   1.119      }
   1.120    }
   1.121 @@ -324,13 +324,13 @@
   1.122    //printf("(%f,%f)\n",path.p[path.numPoints-1].x,path.p[path.numPoints-1].y);
   1.123    for(i = 1;i < path.numPoints;i++) {
   1.124      float d = (float)(SDL_sqrt((path.p[i-1].x-path.p[i].x)*(path.p[i-1].x-path.p[i].x)+
   1.125 -		             (path.p[i-1].y-path.p[i].y)*(path.p[i-1].y-path.p[i].y)));
   1.126 +                             (path.p[i-1].y-path.p[i].y)*(path.p[i-1].y-path.p[i].y)));
   1.127      //printf("d = %f dist = %f/%f\n",d,dist,interval);
   1.128      while(dist + d > interval) {
   1.129        points[numPoints].x = path.p[i-1].x + 
   1.130 -	((interval-dist)/d)*(path.p[i].x-path.p[i-1].x);
   1.131 +        ((interval-dist)/d)*(path.p[i].x-path.p[i-1].x);
   1.132        points[numPoints].y = path.p[i-1].y + 
   1.133 -	((interval-dist)/d)*(path.p[i].y-path.p[i-1].y);
   1.134 +        ((interval-dist)/d)*(path.p[i].y-path.p[i-1].y);
   1.135        centroid.x += points[numPoints].x;
   1.136        centroid.y += points[numPoints].y;
   1.137        numPoints++;
   1.138 @@ -358,9 +358,9 @@
   1.139    ymax = centroid.y;
   1.140    
   1.141    ang = (float)(SDL_atan2(centroid.y - points[0].y,
   1.142 -		    centroid.x - points[0].x));
   1.143 +                    centroid.x - points[0].x));
   1.144  
   1.145 -  for(i = 0;i<numPoints;i++) {					       
   1.146 +  for(i = 0;i<numPoints;i++) {                                               
   1.147      float px = points[i].x;
   1.148      float py = points[i].y;
   1.149      points[i].x = (float)((px - centroid.x)*SDL_cos(ang) - 
   1.150 @@ -387,25 +387,25 @@
   1.151  }
   1.152  
   1.153  float dollarRecognize(SDL_DollarPath path,int *bestTempl,SDL_GestureTouch* touch) {
   1.154 -	
   1.155 -	SDL_FloatPoint points[DOLLARNPOINTS];
   1.156 -	int numPoints = dollarNormalize(path,points);
   1.157 -	int i;
   1.158 -	float bestDiff = 10000;
   1.159 +        
   1.160 +        SDL_FloatPoint points[DOLLARNPOINTS];
   1.161 +        int numPoints = dollarNormalize(path,points);
   1.162 +        int i;
   1.163 +        float bestDiff = 10000;
   1.164  
   1.165 -	//PrintPath(points);
   1.166 -	*bestTempl = -1;
   1.167 -	for(i = 0;i < touch->numDollarTemplates;i++) {
   1.168 -		float diff = bestDollarDifference(points,touch->dollarTemplate[i].path);
   1.169 -		if(diff < bestDiff) {bestDiff = diff; *bestTempl = i;}
   1.170 -	}
   1.171 -	return bestDiff;
   1.172 +        //PrintPath(points);
   1.173 +        *bestTempl = -1;
   1.174 +        for(i = 0;i < touch->numDollarTemplates;i++) {
   1.175 +                float diff = bestDollarDifference(points,touch->dollarTemplate[i].path);
   1.176 +                if(diff < bestDiff) {bestDiff = diff; *bestTempl = i;}
   1.177 +        }
   1.178 +        return bestDiff;
   1.179  }
   1.180  
   1.181  int SDL_GestureAddTouch(SDL_Touch* touch) {  
   1.182    SDL_GestureTouch *gestureTouch = (SDL_GestureTouch *)SDL_realloc(SDL_gestureTouch,
   1.183 -					       (SDL_numGestureTouches + 1) *
   1.184 -					       sizeof(SDL_GestureTouch));
   1.185 +                                               (SDL_numGestureTouches + 1) *
   1.186 +                                               sizeof(SDL_GestureTouch));
   1.187  
   1.188    if(!gestureTouch) {
   1.189      SDL_OutOfMemory();
   1.190 @@ -464,7 +464,7 @@
   1.191  }
   1.192  
   1.193  int SDL_SendGestureDollar(SDL_GestureTouch* touch,
   1.194 -			  SDL_GestureID gestureId,float error) {
   1.195 +                          SDL_GestureID gestureId,float error) {
   1.196    SDL_Event event;
   1.197    event.dgesture.type = SDL_DOLLARGESTURE;
   1.198    event.dgesture.touchId = touch->id;
   1.199 @@ -513,7 +513,7 @@
   1.200      if(inTouch == NULL) return;
   1.201      
   1.202      //printf("@ (%i,%i) with res: (%i,%i)\n",(int)event->tfinger.x,
   1.203 -    //	   (int)event->tfinger.y,
   1.204 +    //           (int)event->tfinger.y,
   1.205      //   (int)inTouch->res.x,(int)inTouch->res.y);
   1.206  
   1.207      
   1.208 @@ -527,44 +527,44 @@
   1.209        
   1.210  #ifdef ENABLE_DOLLAR
   1.211        if(inTouch->recording) {
   1.212 -	inTouch->recording = SDL_FALSE;	
   1.213 -	dollarNormalize(inTouch->dollarPath,path);
   1.214 -	//PrintPath(path);
   1.215 -	if(recordAll) {
   1.216 -	  index = SDL_AddDollarGesture(NULL,path);
   1.217 -	  for(i = 0;i < SDL_numGestureTouches; i++)
   1.218 -	    SDL_gestureTouch[i].recording = SDL_FALSE;
   1.219 -	}
   1.220 -	else {
   1.221 -	  index = SDL_AddDollarGesture(inTouch,path);
   1.222 -	}
   1.223 -	
   1.224 -	if(index >= 0) {
   1.225 -	  SDL_SendDollarRecord(inTouch,inTouch->dollarTemplate[index].hash);
   1.226 -	}
   1.227 -	else {
   1.228 -	  SDL_SendDollarRecord(inTouch,-1);
   1.229 -	}
   1.230 +        inTouch->recording = SDL_FALSE;        
   1.231 +        dollarNormalize(inTouch->dollarPath,path);
   1.232 +        //PrintPath(path);
   1.233 +        if(recordAll) {
   1.234 +          index = SDL_AddDollarGesture(NULL,path);
   1.235 +          for(i = 0;i < SDL_numGestureTouches; i++)
   1.236 +            SDL_gestureTouch[i].recording = SDL_FALSE;
   1.237 +        }
   1.238 +        else {
   1.239 +          index = SDL_AddDollarGesture(inTouch,path);
   1.240 +        }
   1.241 +        
   1.242 +        if(index >= 0) {
   1.243 +          SDL_SendDollarRecord(inTouch,inTouch->dollarTemplate[index].hash);
   1.244 +        }
   1.245 +        else {
   1.246 +          SDL_SendDollarRecord(inTouch,-1);
   1.247 +        }
   1.248        }
   1.249 -      else {	
   1.250 -	int bestTempl;
   1.251 -	float error;
   1.252 -	error = dollarRecognize(inTouch->dollarPath,
   1.253 -				&bestTempl,inTouch);
   1.254 -	if(bestTempl >= 0){
   1.255 -	  //Send Event
   1.256 -	  unsigned long gestureId = inTouch->dollarTemplate[bestTempl].hash;
   1.257 -	  SDL_SendGestureDollar(inTouch,gestureId,error);
   1.258 -	  //printf ("%s\n",);("Dollar error: %f\n",error);
   1.259 -	}
   1.260 +      else {        
   1.261 +        int bestTempl;
   1.262 +        float error;
   1.263 +        error = dollarRecognize(inTouch->dollarPath,
   1.264 +                                &bestTempl,inTouch);
   1.265 +        if(bestTempl >= 0){
   1.266 +          //Send Event
   1.267 +          unsigned long gestureId = inTouch->dollarTemplate[bestTempl].hash;
   1.268 +          SDL_SendGestureDollar(inTouch,gestureId,error);
   1.269 +          //printf ("%s\n",);("Dollar error: %f\n",error);
   1.270 +        }
   1.271        }
   1.272  #endif 
   1.273        //inTouch->gestureLast[j] = inTouch->gestureLast[inTouch->numDownFingers];
   1.274        if(inTouch->numDownFingers > 0) {
   1.275 -	inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers+1)-
   1.276 -			       x)/inTouch->numDownFingers;
   1.277 -	inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers+1)-
   1.278 -			       y)/inTouch->numDownFingers;
   1.279 +        inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers+1)-
   1.280 +                               x)/inTouch->numDownFingers;
   1.281 +        inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers+1)-
   1.282 +                               y)/inTouch->numDownFingers;
   1.283        }
   1.284      }
   1.285      else if(event->type == SDL_FINGERMOTION) {
   1.286 @@ -574,14 +574,14 @@
   1.287  #ifdef ENABLE_DOLLAR
   1.288        SDL_DollarPath* path = &inTouch->dollarPath;
   1.289        if(path->numPoints < MAXPATHSIZE) {
   1.290 -	path->p[path->numPoints].x = inTouch->centroid.x;
   1.291 -	path->p[path->numPoints].y = inTouch->centroid.y;
   1.292 -	pathDx = 
   1.293 -	  (path->p[path->numPoints].x-path->p[path->numPoints-1].x);
   1.294 -	pathDy = 
   1.295 -	  (path->p[path->numPoints].y-path->p[path->numPoints-1].y);
   1.296 -	path->length += (float)SDL_sqrt(pathDx*pathDx + pathDy*pathDy);
   1.297 -	path->numPoints++;
   1.298 +        path->p[path->numPoints].x = inTouch->centroid.x;
   1.299 +        path->p[path->numPoints].y = inTouch->centroid.y;
   1.300 +        pathDx = 
   1.301 +          (path->p[path->numPoints].x-path->p[path->numPoints-1].x);
   1.302 +        pathDy = 
   1.303 +          (path->p[path->numPoints].y-path->p[path->numPoints-1].y);
   1.304 +        path->length += (float)SDL_sqrt(pathDx*pathDx + pathDy*pathDy);
   1.305 +        path->numPoints++;
   1.306        }
   1.307  #endif
   1.308        lastP.x = x - dx;
   1.309 @@ -592,46 +592,46 @@
   1.310        inTouch->centroid.y += dy/inTouch->numDownFingers;
   1.311        //printf("Centrid : (%f,%f)\n",inTouch->centroid.x,inTouch->centroid.y);
   1.312        if(inTouch->numDownFingers > 1) {
   1.313 -	SDL_FloatPoint lv; //Vector from centroid to last x,y position
   1.314 -	SDL_FloatPoint v; //Vector from centroid to current x,y position
   1.315 -	//lv = inTouch->gestureLast[j].cv;
   1.316 -	lv.x = lastP.x - lastCentroid.x;
   1.317 -	lv.y = lastP.y - lastCentroid.y;
   1.318 -	lDist = (float)SDL_sqrt(lv.x*lv.x + lv.y*lv.y);
   1.319 -	//printf("lDist = %f\n",lDist);
   1.320 -	v.x = x - inTouch->centroid.x;
   1.321 -	v.y = y - inTouch->centroid.y;
   1.322 -	//inTouch->gestureLast[j].cv = v;
   1.323 -	Dist = (float)SDL_sqrt(v.x*v.x+v.y*v.y);
   1.324 -	// SDL_cos(dTheta) = (v . lv)/(|v| * |lv|)
   1.325 -	
   1.326 -	//Normalize Vectors to simplify angle calculation
   1.327 -	lv.x/=lDist;
   1.328 -	lv.y/=lDist;
   1.329 -	v.x/=Dist;
   1.330 -	v.y/=Dist;
   1.331 -	dtheta = (float)SDL_atan2(lv.x*v.y - lv.y*v.x,lv.x*v.x + lv.y*v.y);
   1.332 -	
   1.333 -	dDist = (Dist - lDist);
   1.334 -	if(lDist == 0) {dDist = 0;dtheta = 0;} //To avoid impossible values
   1.335 -	
   1.336 -	//inTouch->gestureLast[j].dDist = dDist;
   1.337 -	//inTouch->gestureLast[j].dtheta = dtheta;
   1.338 -	
   1.339 -	//printf("dDist = %f, dTheta = %f\n",dDist,dtheta);
   1.340 -	//gdtheta = gdtheta*.9 + dtheta*.1;
   1.341 -	//gdDist  =  gdDist*.9 +  dDist*.1
   1.342 -	//knob.r += dDist/numDownFingers;
   1.343 -	//knob.ang += dtheta;
   1.344 -	//printf("thetaSum = %f, distSum = %f\n",gdtheta,gdDist);
   1.345 -	//printf("id: %i dTheta = %f, dDist = %f\n",j,dtheta,dDist);
   1.346 -	SDL_SendGestureMulti(inTouch,dtheta,dDist);
   1.347 +        SDL_FloatPoint lv; //Vector from centroid to last x,y position
   1.348 +        SDL_FloatPoint v; //Vector from centroid to current x,y position
   1.349 +        //lv = inTouch->gestureLast[j].cv;
   1.350 +        lv.x = lastP.x - lastCentroid.x;
   1.351 +        lv.y = lastP.y - lastCentroid.y;
   1.352 +        lDist = (float)SDL_sqrt(lv.x*lv.x + lv.y*lv.y);
   1.353 +        //printf("lDist = %f\n",lDist);
   1.354 +        v.x = x - inTouch->centroid.x;
   1.355 +        v.y = y - inTouch->centroid.y;
   1.356 +        //inTouch->gestureLast[j].cv = v;
   1.357 +        Dist = (float)SDL_sqrt(v.x*v.x+v.y*v.y);
   1.358 +        // SDL_cos(dTheta) = (v . lv)/(|v| * |lv|)
   1.359 +        
   1.360 +        //Normalize Vectors to simplify angle calculation
   1.361 +        lv.x/=lDist;
   1.362 +        lv.y/=lDist;
   1.363 +        v.x/=Dist;
   1.364 +        v.y/=Dist;
   1.365 +        dtheta = (float)SDL_atan2(lv.x*v.y - lv.y*v.x,lv.x*v.x + lv.y*v.y);
   1.366 +        
   1.367 +        dDist = (Dist - lDist);
   1.368 +        if(lDist == 0) {dDist = 0;dtheta = 0;} //To avoid impossible values
   1.369 +        
   1.370 +        //inTouch->gestureLast[j].dDist = dDist;
   1.371 +        //inTouch->gestureLast[j].dtheta = dtheta;
   1.372 +        
   1.373 +        //printf("dDist = %f, dTheta = %f\n",dDist,dtheta);
   1.374 +        //gdtheta = gdtheta*.9 + dtheta*.1;
   1.375 +        //gdDist  =  gdDist*.9 +  dDist*.1
   1.376 +        //knob.r += dDist/numDownFingers;
   1.377 +        //knob.ang += dtheta;
   1.378 +        //printf("thetaSum = %f, distSum = %f\n",gdtheta,gdDist);
   1.379 +        //printf("id: %i dTheta = %f, dDist = %f\n",j,dtheta,dDist);
   1.380 +        SDL_SendGestureMulti(inTouch,dtheta,dDist);
   1.381        }
   1.382        else {
   1.383 -	//inTouch->gestureLast[j].dDist = 0;
   1.384 -	//inTouch->gestureLast[j].dtheta = 0;
   1.385 -	//inTouch->gestureLast[j].cv.x = 0;
   1.386 -	//inTouch->gestureLast[j].cv.y = 0;
   1.387 +        //inTouch->gestureLast[j].dDist = 0;
   1.388 +        //inTouch->gestureLast[j].dtheta = 0;
   1.389 +        //inTouch->gestureLast[j].cv.x = 0;
   1.390 +        //inTouch->gestureLast[j].cv.y = 0;
   1.391        }
   1.392        //inTouch->gestureLast[j].f.p.x = x;
   1.393        //inTouch->gestureLast[j].f.p.y = y;
   1.394 @@ -643,9 +643,9 @@
   1.395  
   1.396        inTouch->numDownFingers++;
   1.397        inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers - 1)+ 
   1.398 -			     x)/inTouch->numDownFingers;
   1.399 +                             x)/inTouch->numDownFingers;
   1.400        inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers - 1)+
   1.401 -			     y)/inTouch->numDownFingers;
   1.402 +                             y)/inTouch->numDownFingers;
   1.403        //printf("Finger Down: (%f,%f). Centroid: (%f,%f\n",x,y,
   1.404        //     inTouch->centroid.x,inTouch->centroid.y);
   1.405  
     2.1 --- a/src/events/SDL_touch.c	Tue Nov 30 12:38:46 2010 -0800
     2.2 +++ b/src/events/SDL_touch.c	Tue Nov 30 17:58:51 2010 -0800
     2.3 @@ -65,8 +65,8 @@
     2.4  {
     2.5      int i;
     2.6      for(i = 0;i < touch->num_fingers;i++)
     2.7 -	if(touch->fingers[i]->id == fingerid)
     2.8 -	    return i;
     2.9 +        if(touch->fingers[i]->id == fingerid)
    2.10 +            return i;
    2.11      return -1;
    2.12  }
    2.13  
    2.14 @@ -76,7 +76,7 @@
    2.15  {
    2.16      int index = SDL_GetFingerIndexId(touch,id);
    2.17      if(index < 0 || index >= touch->num_fingers)
    2.18 -	return NULL;
    2.19 +        return NULL;
    2.20      return touch->fingers[index];
    2.21  }
    2.22  
    2.23 @@ -259,22 +259,22 @@
    2.24      //printf("Adding Finger...\n");
    2.25      if (SDL_GetFingerIndexId(touch,finger->id) != -1) {
    2.26          SDL_SetError("Finger ID already in use");
    2.27 -	}
    2.28 +        }
    2.29  
    2.30      /* Add the touch to the list of touch */
    2.31      if(touch->num_fingers  >= touch->max_fingers){
    2.32 -		//printf("Making room for it!\n");
    2.33 -		fingers = (SDL_Finger **) SDL_realloc(touch->fingers,
    2.34 -  						   (touch->num_fingers + 1) * sizeof(SDL_Finger *));
    2.35 -		touch->max_fingers = touch->num_fingers+1;
    2.36 -		if (!fingers) {
    2.37 -			SDL_OutOfMemory();
    2.38 -			return -1;
    2.39 -		} else {
    2.40 -			touch->max_fingers = touch->num_fingers+1;
    2.41 -			touch->fingers = fingers;
    2.42 -		}
    2.43 -	}
    2.44 +                //printf("Making room for it!\n");
    2.45 +                fingers = (SDL_Finger **) SDL_realloc(touch->fingers,
    2.46 +                                                     (touch->num_fingers + 1) * sizeof(SDL_Finger *));
    2.47 +                touch->max_fingers = touch->num_fingers+1;
    2.48 +                if (!fingers) {
    2.49 +                        SDL_OutOfMemory();
    2.50 +                        return -1;
    2.51 +                } else {
    2.52 +                        touch->max_fingers = touch->num_fingers+1;
    2.53 +                        touch->fingers = fingers;
    2.54 +                }
    2.55 +        }
    2.56  
    2.57      index = touch->num_fingers;
    2.58      //printf("Max_Fingers: %i Index: %i\n",touch->max_fingers,index);
    2.59 @@ -310,13 +310,13 @@
    2.60  
    2.61  int
    2.62  SDL_SendFingerDown(SDL_TouchID id, SDL_FingerID fingerid, SDL_bool down, 
    2.63 -		   float xin, float yin, float pressurein)
    2.64 +                   float xin, float yin, float pressurein)
    2.65  {
    2.66      int posted;
    2.67 -	Uint16 x;
    2.68 -	Uint16 y;
    2.69 -	Uint16 pressure;
    2.70 -	SDL_Finger *finger;
    2.71 +        Uint16 x;
    2.72 +        Uint16 y;
    2.73 +        Uint16 pressure;
    2.74 +        SDL_Finger *finger;
    2.75  
    2.76      SDL_Touch* touch = SDL_GetTouch(id);
    2.77  
    2.78 @@ -332,68 +332,68 @@
    2.79      
    2.80      finger = SDL_GetFinger(touch,fingerid);
    2.81      if(down) {
    2.82 -	if(finger == NULL) {
    2.83 -	    SDL_Finger nf;
    2.84 -	    nf.id = fingerid;
    2.85 -	    nf.x = x;
    2.86 -	    nf.y = y;
    2.87 -	    nf.pressure = pressure;
    2.88 -	    nf.xdelta = 0;
    2.89 -	    nf.ydelta = 0;
    2.90 -	    nf.last_x = x;
    2.91 -	    nf.last_y = y;
    2.92 -	    nf.last_pressure = pressure;
    2.93 -	    nf.down = SDL_FALSE;
    2.94 -	    if(SDL_AddFinger(touch,&nf) < 0) return 0;
    2.95 -	    finger = SDL_GetFinger(touch,fingerid);
    2.96 -	}
    2.97 -	else if(finger->down) return 0;
    2.98 -	if(xin < touch->x_min || yin < touch->y_min) return 0; //should defer if only a partial input
    2.99 -	posted = 0;
   2.100 -	if (SDL_GetEventState(SDL_FINGERDOWN) == SDL_ENABLE) {
   2.101 -	    SDL_Event event;
   2.102 -	    event.tfinger.type = SDL_FINGERDOWN;
   2.103 -	    event.tfinger.touchId = id;
   2.104 -	    event.tfinger.x = x;
   2.105 -	    event.tfinger.y = y;
   2.106 -	    event.tfinger.pressure = pressure;
   2.107 -	    event.tfinger.state = touch->buttonstate;
   2.108 -	    event.tfinger.windowID = touch->focus ? touch->focus->id : 0;
   2.109 -	    event.tfinger.fingerId = fingerid;
   2.110 -	    posted = (SDL_PushEvent(&event) > 0);
   2.111 -	}
   2.112 -	if(posted) finger->down = SDL_TRUE;
   2.113 -	return posted;
   2.114 +        if(finger == NULL) {
   2.115 +            SDL_Finger nf;
   2.116 +            nf.id = fingerid;
   2.117 +            nf.x = x;
   2.118 +            nf.y = y;
   2.119 +            nf.pressure = pressure;
   2.120 +            nf.xdelta = 0;
   2.121 +            nf.ydelta = 0;
   2.122 +            nf.last_x = x;
   2.123 +            nf.last_y = y;
   2.124 +            nf.last_pressure = pressure;
   2.125 +            nf.down = SDL_FALSE;
   2.126 +            if(SDL_AddFinger(touch,&nf) < 0) return 0;
   2.127 +            finger = SDL_GetFinger(touch,fingerid);
   2.128 +        }
   2.129 +        else if(finger->down) return 0;
   2.130 +        if(xin < touch->x_min || yin < touch->y_min) return 0; //should defer if only a partial input
   2.131 +        posted = 0;
   2.132 +        if (SDL_GetEventState(SDL_FINGERDOWN) == SDL_ENABLE) {
   2.133 +            SDL_Event event;
   2.134 +            event.tfinger.type = SDL_FINGERDOWN;
   2.135 +            event.tfinger.touchId = id;
   2.136 +            event.tfinger.x = x;
   2.137 +            event.tfinger.y = y;
   2.138 +            event.tfinger.pressure = pressure;
   2.139 +            event.tfinger.state = touch->buttonstate;
   2.140 +            event.tfinger.windowID = touch->focus ? touch->focus->id : 0;
   2.141 +            event.tfinger.fingerId = fingerid;
   2.142 +            posted = (SDL_PushEvent(&event) > 0);
   2.143 +        }
   2.144 +        if(posted) finger->down = SDL_TRUE;
   2.145 +        return posted;
   2.146      }
   2.147      else {
   2.148          if(finger == NULL) {
   2.149              SDL_SetError("Finger not found.");
   2.150              return 0;
   2.151          }      
   2.152 -	posted = 0;
   2.153 -	if (SDL_GetEventState(SDL_FINGERUP) == SDL_ENABLE) {
   2.154 -	    SDL_Event event;
   2.155 -	    event.tfinger.type = SDL_FINGERUP;
   2.156 -	    event.tfinger.touchId =  id;
   2.157 -	    event.tfinger.state = touch->buttonstate;
   2.158 -	    event.tfinger.windowID = touch->focus ? touch->focus->id : 0;
   2.159 -	    event.tfinger.fingerId = fingerid;
   2.160 -	    //I don't trust the coordinates passed on fingerUp
   2.161 -	    event.tfinger.x = finger->x; 
   2.162 -	    event.tfinger.y = finger->y;
   2.163 -	    event.tfinger.dx = 0;
   2.164 -	    event.tfinger.dy = 0;
   2.165 +        posted = 0;
   2.166 +        if (SDL_GetEventState(SDL_FINGERUP) == SDL_ENABLE) {
   2.167 +            SDL_Event event;
   2.168 +            event.tfinger.type = SDL_FINGERUP;
   2.169 +            event.tfinger.touchId =  id;
   2.170 +            event.tfinger.state = touch->buttonstate;
   2.171 +            event.tfinger.windowID = touch->focus ? touch->focus->id : 0;
   2.172 +            event.tfinger.fingerId = fingerid;
   2.173 +            //I don't trust the coordinates passed on fingerUp
   2.174 +            event.tfinger.x = finger->x; 
   2.175 +            event.tfinger.y = finger->y;
   2.176 +            event.tfinger.dx = 0;
   2.177 +            event.tfinger.dy = 0;
   2.178  
   2.179 -	    if(SDL_DelFinger(touch,fingerid) < 0) return 0;
   2.180 -	    posted = (SDL_PushEvent(&event) > 0);
   2.181 -	}	
   2.182 -	return posted;
   2.183 +            if(SDL_DelFinger(touch,fingerid) < 0) return 0;
   2.184 +            posted = (SDL_PushEvent(&event) > 0);
   2.185 +        }        
   2.186 +        return posted;
   2.187      }
   2.188  }
   2.189  
   2.190  int
   2.191  SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, int relative, 
   2.192 -		    float xin, float yin, float pressurein)
   2.193 +                    float xin, float yin, float pressurein)
   2.194  {
   2.195      int index = SDL_GetTouchIndexId(id);
   2.196      SDL_Touch *touch = SDL_GetTouch(id);
   2.197 @@ -401,9 +401,9 @@
   2.198      int posted;
   2.199      Sint16 xrel, yrel;
   2.200      float x_max = 0, y_max = 0;
   2.201 -	Uint16 x;
   2.202 -	Uint16 y;
   2.203 -	Uint16 pressure;
   2.204 +        Uint16 x;
   2.205 +        Uint16 y;
   2.206 +        Uint16 pressure;
   2.207      
   2.208      if (!touch) {
   2.209        return SDL_TouchNotFoundError(id);
   2.210 @@ -414,85 +414,85 @@
   2.211      y = (Uint16)((yin+touch->y_min)*(touch->yres)/(touch->native_yres));
   2.212      pressure = (Uint16)((yin+touch->pressure_min)*(touch->pressureres)/(touch->native_pressureres));
   2.213      if(touch->flush_motion) {
   2.214 -	return 0;
   2.215 +        return 0;
   2.216      }
   2.217      
   2.218      if(finger == NULL || !finger->down) {
   2.219 -	return SDL_SendFingerDown(id,fingerid,SDL_TRUE,xin,yin,pressurein);	
   2.220 +        return SDL_SendFingerDown(id,fingerid,SDL_TRUE,xin,yin,pressurein);        
   2.221      } else {
   2.222 -	/* the relative motion is calculated regarding the last position */
   2.223 -	if (relative) {
   2.224 -	    xrel = x;
   2.225 -	    yrel = y;
   2.226 -	    x = (finger->last_x + x);
   2.227 -	    y = (finger->last_y + y);
   2.228 -	} else {
   2.229 -	    if(xin < touch->x_min) x = finger->last_x; /*If movement is only in one axis,*/
   2.230 -	    if(yin < touch->y_min) y = finger->last_y; /*The other is marked as -1*/
   2.231 -	    if(pressurein < touch->pressure_min) pressure = finger->last_pressure;
   2.232 -	    xrel = x - finger->last_x;
   2.233 -	    yrel = y - finger->last_y;
   2.234 -	    //printf("xrel,yrel (%i,%i)\n",(int)xrel,(int)yrel);
   2.235 -	}
   2.236 -	
   2.237 -	/* Drop events that don't change state */
   2.238 -	if (!xrel && !yrel) {
   2.239 +        /* the relative motion is calculated regarding the last position */
   2.240 +        if (relative) {
   2.241 +            xrel = x;
   2.242 +            yrel = y;
   2.243 +            x = (finger->last_x + x);
   2.244 +            y = (finger->last_y + y);
   2.245 +        } else {
   2.246 +            if(xin < touch->x_min) x = finger->last_x; /*If movement is only in one axis,*/
   2.247 +            if(yin < touch->y_min) y = finger->last_y; /*The other is marked as -1*/
   2.248 +            if(pressurein < touch->pressure_min) pressure = finger->last_pressure;
   2.249 +            xrel = x - finger->last_x;
   2.250 +            yrel = y - finger->last_y;
   2.251 +            //printf("xrel,yrel (%i,%i)\n",(int)xrel,(int)yrel);
   2.252 +        }
   2.253 +        
   2.254 +        /* Drop events that don't change state */
   2.255 +        if (!xrel && !yrel) {
   2.256  #if 0
   2.257 -	    printf("Touch event didn't change state - dropped!\n");
   2.258 +            printf("Touch event didn't change state - dropped!\n");
   2.259  #endif
   2.260 -	    return 0;
   2.261 -	}
   2.262 -	
   2.263 -	/* Update internal touch coordinates */
   2.264 -	
   2.265 -	finger->x = x;
   2.266 -	finger->y = y;
   2.267 -	
   2.268 -	/*Should scale to window? Normalize? Maintain Aspect?*/
   2.269 -	//SDL_GetWindowSize(touch->focus, &x_max, &y_max);
   2.270 -	
   2.271 -	/* make sure that the pointers find themselves inside the windows */
   2.272 -	/* only check if touch->xmax is set ! */
   2.273 -	/*
   2.274 -	  if (x_max && touch->x > x_max) {
   2.275 -	  touch->x = x_max;
   2.276 -	  } else if (touch->x < 0) {
   2.277 -	  touch->x = 0;
   2.278 -	  }
   2.279 -	  
   2.280 -	  if (y_max && touch->y > y_max) {
   2.281 -	  touch->y = y_max;
   2.282 -	  } else if (touch->y < 0) {
   2.283 -	  touch->y = 0;
   2.284 -	  }
   2.285 -	*/
   2.286 -	finger->xdelta = xrel;
   2.287 -	finger->ydelta = yrel;
   2.288 -	finger->pressure = pressure;
   2.289 -	
   2.290 -	
   2.291 -	
   2.292 -	/* Post the event, if desired */
   2.293 -	posted = 0;
   2.294 -	if (SDL_GetEventState(SDL_FINGERMOTION) == SDL_ENABLE) {
   2.295 -	    SDL_Event event;
   2.296 -	    event.tfinger.type = SDL_FINGERMOTION;
   2.297 -	    event.tfinger.touchId = id;
   2.298 -	    event.tfinger.fingerId = fingerid;
   2.299 -	    event.tfinger.x = x;
   2.300 -	    event.tfinger.y = y;
   2.301 -	    event.tfinger.dx = xrel;
   2.302 -	    event.tfinger.dy = yrel;	    
   2.303 -		
   2.304 -	    event.tfinger.pressure = pressure;
   2.305 -	    event.tfinger.state = touch->buttonstate;
   2.306 -	    event.tfinger.windowID = touch->focus ? touch->focus->id : 0;
   2.307 -	    posted = (SDL_PushEvent(&event) > 0);
   2.308 -	}
   2.309 -	finger->last_x = finger->x;
   2.310 -	finger->last_y = finger->y;
   2.311 -	finger->last_pressure = finger->pressure;
   2.312 -	return posted;
   2.313 +            return 0;
   2.314 +        }
   2.315 +        
   2.316 +        /* Update internal touch coordinates */
   2.317 +        
   2.318 +        finger->x = x;
   2.319 +        finger->y = y;
   2.320 +        
   2.321 +        /*Should scale to window? Normalize? Maintain Aspect?*/
   2.322 +        //SDL_GetWindowSize(touch->focus, &x_max, &y_max);
   2.323 +        
   2.324 +        /* make sure that the pointers find themselves inside the windows */
   2.325 +        /* only check if touch->xmax is set ! */
   2.326 +        /*
   2.327 +          if (x_max && touch->x > x_max) {
   2.328 +          touch->x = x_max;
   2.329 +          } else if (touch->x < 0) {
   2.330 +          touch->x = 0;
   2.331 +          }
   2.332 +          
   2.333 +          if (y_max && touch->y > y_max) {
   2.334 +          touch->y = y_max;
   2.335 +          } else if (touch->y < 0) {
   2.336 +          touch->y = 0;
   2.337 +          }
   2.338 +        */
   2.339 +        finger->xdelta = xrel;
   2.340 +        finger->ydelta = yrel;
   2.341 +        finger->pressure = pressure;
   2.342 +        
   2.343 +        
   2.344 +        
   2.345 +        /* Post the event, if desired */
   2.346 +        posted = 0;
   2.347 +        if (SDL_GetEventState(SDL_FINGERMOTION) == SDL_ENABLE) {
   2.348 +            SDL_Event event;
   2.349 +            event.tfinger.type = SDL_FINGERMOTION;
   2.350 +            event.tfinger.touchId = id;
   2.351 +            event.tfinger.fingerId = fingerid;
   2.352 +            event.tfinger.x = x;
   2.353 +            event.tfinger.y = y;
   2.354 +            event.tfinger.dx = xrel;
   2.355 +            event.tfinger.dy = yrel;            
   2.356 +                
   2.357 +            event.tfinger.pressure = pressure;
   2.358 +            event.tfinger.state = touch->buttonstate;
   2.359 +            event.tfinger.windowID = touch->focus ? touch->focus->id : 0;
   2.360 +            posted = (SDL_PushEvent(&event) > 0);
   2.361 +        }
   2.362 +        finger->last_x = finger->x;
   2.363 +        finger->last_y = finger->y;
   2.364 +        finger->last_pressure = finger->pressure;
   2.365 +        return posted;
   2.366      }
   2.367  }
   2.368  int
     3.1 --- a/src/video/win32/SDL_win32events.c	Tue Nov 30 12:38:46 2010 -0800
     3.2 +++ b/src/video/win32/SDL_win32events.c	Tue Nov 30 17:58:51 2010 -0800
     3.3 @@ -27,6 +27,7 @@
     3.4  #include "SDL_syswm.h"
     3.5  #include "SDL_vkeys.h"
     3.6  #include "../../events/SDL_events_c.h"
     3.7 +#include "../../events/SDL_touch_c.h"
     3.8  
     3.9  
    3.10  
    3.11 @@ -55,12 +56,10 @@
    3.12  #ifndef WM_INPUT
    3.13  #define WM_INPUT 0x00ff
    3.14  #endif
    3.15 -#ifndef WM_GESTURE
    3.16 -#define WM_GESTURE 0x0119
    3.17 -#endif
    3.18  #ifndef WM_TOUCH
    3.19  #define WM_TOUCH 0x0240
    3.20 -#endif
    3.21 +#endif
    3.22 +
    3.23  
    3.24  static WPARAM
    3.25  RemapVKEY(WPARAM wParam, LPARAM lParam)
    3.26 @@ -519,41 +518,70 @@
    3.27          }
    3.28          returnCode = 0;
    3.29          break;
    3.30 +
    3.31  	case WM_TOUCH:
    3.32 -		{
    3.33 -			//printf("Got Touch Event!\n");
    3.34 -    
    3.35 -#ifdef WMMSG_DEBUG
    3.36 -			FILE *log = fopen("wmmsg.txt", "a");
    3.37 -			fprintf(log, "Received Touch Message: %p ", hwnd);
    3.38 -			if (msg > MAX_WMMSG) {
    3.39 -				fprintf(log, "%d", msg);
    3.40 -			} else {
    3.41 -				fprintf(log, "%s", wmtab[msg]);
    3.42 -			}
    3.43 -			fprintf(log, "WM_TOUCH = %d -- 0x%X, 0x%X\n",msg, wParam, lParam);
    3.44 -			fclose(log);
    3.45 -#endif
    3.46 -    
    3.47 +		{
    3.48 +			UINT i, num_inputs = LOWORD(wParam);
    3.49 +			PTOUCHINPUT inputs = SDL_stack_alloc(TOUCHINPUT, num_inputs);
    3.50 +			if (data->videodata->GetTouchInputInfo((HTOUCHINPUT)lParam, num_inputs, inputs, sizeof(TOUCHINPUT))) {
    3.51 +				RECT rect;
    3.52 +				float x, y;
    3.53 +
    3.54 +				if (!GetClientRect(hwnd, &rect) ||
    3.55 +				    (rect.right == rect.left && rect.bottom == rect.top)) {
    3.56 +					break;
    3.57 +				}
    3.58 +				ClientToScreen(hwnd, (LPPOINT) & rect);
    3.59 +				ClientToScreen(hwnd, (LPPOINT) & rect + 1);
    3.60 +				rect.top *= 100;
    3.61 +				rect.left *= 100;
    3.62 +				rect.bottom *= 100;
    3.63 +				rect.right *= 100;
    3.64 +
    3.65 +				for (i = 0; i < num_inputs; ++i) {
    3.66 +					PTOUCHINPUT input = &inputs[i];
    3.67 +
    3.68 +					SDL_TouchID touchId = (SDL_TouchID)input->hSource;
    3.69 +					if (!SDL_GetTouch(touchId)) {
    3.70 +						SDL_Touch touch;
    3.71 +
    3.72 +						touch.id = touchId;
    3.73 +						touch.x_min = 0;
    3.74 +						touch.x_max = 1;
    3.75 +						touch.native_xres = touch.x_max - touch.x_min;
    3.76 +						touch.y_min = 0;
    3.77 +						touch.y_max = 1;
    3.78 +						touch.native_yres = touch.y_max - touch.y_min;
    3.79 +						touch.pressure_min = 0;
    3.80 +						touch.pressure_max = 1;
    3.81 +						touch.native_pressureres = touch.pressure_max - touch.pressure_min;
    3.82 +
    3.83 +						if (SDL_AddTouch(&touch, "") < 0) {
    3.84 +							continue;
    3.85 +						}
    3.86 +					}
    3.87 +
    3.88 +					// Get the normalized coordinates for the window
    3.89 +					x = (float)(input->x - rect.left)/(rect.right - rect.left);
    3.90 +					y = (float)(input->y - rect.top)/(rect.bottom - rect.top);
    3.91 +
    3.92 +					if (input->dwFlags & TOUCHEVENTF_DOWN) {
    3.93 +						SDL_SendFingerDown(touchId, input->dwID, SDL_TRUE, x, y, 1);
    3.94 +					}
    3.95 +					if (input->dwFlags & TOUCHEVENTF_MOVE) {
    3.96 +						SDL_SendTouchMotion(touchId, input->dwID, SDL_FALSE, x, y, 1);
    3.97 +					}
    3.98 +					if (input->dwFlags & TOUCHEVENTF_UP) {
    3.99 +						SDL_SendFingerDown(touchId, input->dwID, SDL_FALSE, x, y, 1);
   3.100 +					}
   3.101 +				}
   3.102 +			}
   3.103 +			SDL_stack_free(inputs);
   3.104 +
   3.105 +			data->videodata->CloseTouchInputHandle((HTOUCHINPUT)lParam);
   3.106 +			return 0;
   3.107  		}
   3.108  		break;
   3.109 -	case WM_GESTURE:
   3.110 -		{
   3.111 -			//printf("Got Touch Event!\n");
   3.112 -    
   3.113 -#ifdef WMMSG_DEBUG
   3.114 -			FILE *log = fopen("wmmsg.txt", "a");
   3.115 -			fprintf(log, "Received Gesture Message: %p ", hwnd);
   3.116 -			if (msg > MAX_WMMSG) {
   3.117 -				fprintf(log, "%d", msg);
   3.118 -			} else {
   3.119 -				fprintf(log, "%s", wmtab[msg]);
   3.120 -			}
   3.121 -			fprintf(log, "WM_GESTURE = %d -- 0x%X, 0x%X\n",msg, wParam, lParam);
   3.122 -			fclose(log);
   3.123 -#endif
   3.124 -		}
   3.125 -		break;		
   3.126  	}
   3.127  
   3.128      /* If there's a window proc, assume it's going to handle messages */
     4.1 --- a/src/video/win32/SDL_win32video.c	Tue Nov 30 12:38:46 2010 -0800
     4.2 +++ b/src/video/win32/SDL_win32video.c	Tue Nov 30 17:58:51 2010 -0800
     4.3 @@ -82,6 +82,10 @@
     4.4         FreeLibrary(data->hAygShell);
     4.5      }
     4.6  #endif
     4.7 +	if (data->userDLL) {
     4.8 +		FreeLibrary(data->userDLL);
     4.9 +	}
    4.10 +
    4.11      SDL_free(device->driverdata);
    4.12      SDL_free(device);
    4.13  }
    4.14 @@ -155,6 +159,13 @@
    4.15      data->CoordTransform = NULL;
    4.16  #endif
    4.17  
    4.18 +	data->userDLL = LoadLibrary(TEXT("USER32.DLL"));
    4.19 +	if (data->userDLL) {
    4.20 +		data->CloseTouchInputHandle = (BOOL (WINAPI *)( HTOUCHINPUT )) GetProcAddress(data->userDLL, "CloseTouchInputHandle");
    4.21 +		data->GetTouchInputInfo = (BOOL (WINAPI *)( HTOUCHINPUT, UINT, PTOUCHINPUT, int )) GetProcAddress(data->userDLL, "GetTouchInputInfo");
    4.22 +		data->RegisterTouchWindow = (BOOL (WINAPI *)( HWND, ULONG )) GetProcAddress(data->userDLL, "RegisterTouchWindow");
    4.23 +	}
    4.24 +
    4.25      /* Set the function pointers */
    4.26      device->VideoInit = WIN_VideoInit;
    4.27      device->VideoQuit = WIN_VideoQuit;
     5.1 --- a/src/video/win32/SDL_win32video.h	Tue Nov 30 12:38:46 2010 -0800
     5.2 +++ b/src/video/win32/SDL_win32video.h	Tue Nov 30 17:58:51 2010 -0800
     5.3 @@ -80,6 +80,32 @@
     5.4  
     5.5  enum { RENDER_NONE, RENDER_D3D, RENDER_DDRAW, RENDER_GDI, RENDER_GAPI, RENDER_RAW };
     5.6  
     5.7 +#if WINVER < 0x0601
     5.8 +/* Touch input definitions */
     5.9 +#define TWF_FINETOUCH	1
    5.10 +#define TWF_WANTPALM	2
    5.11 +
    5.12 +#define TOUCHEVENTF_MOVE 0x0001
    5.13 +#define TOUCHEVENTF_DOWN 0x0002
    5.14 +#define TOUCHEVENTF_UP   0x0004
    5.15 +
    5.16 +DECLARE_HANDLE(HTOUCHINPUT);
    5.17 +
    5.18 +typedef struct _TOUCHINPUT {
    5.19 +	LONG      x;
    5.20 +	LONG      y;
    5.21 +	HANDLE    hSource;
    5.22 +	DWORD     dwID;
    5.23 +	DWORD     dwFlags;
    5.24 +	DWORD     dwMask;
    5.25 +	DWORD     dwTime;
    5.26 +	ULONG_PTR dwExtraInfo;
    5.27 +	DWORD     cxContact;
    5.28 +	DWORD     cyContact;
    5.29 +} TOUCHINPUT, *PTOUCHINPUT;
    5.30 +
    5.31 +#endif /* WINVER < 0x0601 */
    5.32 +
    5.33  typedef BOOL  (*PFNSHFullScreen)(HWND, DWORD);
    5.34  typedef void  (*PFCoordTransform)(SDL_Window*, POINT*);
    5.35  
    5.36 @@ -135,7 +161,13 @@
    5.37  #endif
    5.38  
    5.39      const SDL_scancode *key_layout;
    5.40 -    DWORD clipboard_count;
    5.41 +	DWORD clipboard_count;
    5.42 +
    5.43 +	/* Touch input functions */
    5.44 +	HANDLE userDLL;
    5.45 +	BOOL (WINAPI *CloseTouchInputHandle)( HTOUCHINPUT );
    5.46 +	BOOL (WINAPI *GetTouchInputInfo)( HTOUCHINPUT, UINT, PTOUCHINPUT, int );
    5.47 +	BOOL (WINAPI *RegisterTouchWindow)( HWND, ULONG );
    5.48  
    5.49      SDL_bool ime_com_initialized;
    5.50      struct ITfThreadMgr *ime_threadmgr;
     6.1 --- a/src/video/win32/SDL_win32window.c	Tue Nov 30 12:38:46 2010 -0800
     6.2 +++ b/src/video/win32/SDL_win32window.c	Tue Nov 30 17:58:51 2010 -0800
     6.3 @@ -144,6 +144,9 @@
     6.4          }
     6.5      }
     6.6  
     6.7 +	/* Enable multi-touch */
     6.8 +	videodata->RegisterTouchWindow(hwnd, (TWF_FINETOUCH|TWF_WANTPALM));
     6.9 +
    6.10      /* All done! */
    6.11      window->driverdata = data;
    6.12      return 0;