søndag den 13. marts 2011

Mac OS X multitouch

Here's some code I found to directly access the touchpad state of fx. the MacBook from C++ code. It uses the Apple MultitouchSupport framework (which comes with XCode) and can be compiled with G++ like this:

g++ -L/System/Library/PrivateFrameworks/MultitouchSupport.framework \
-F/System/Library/PrivateFrameworks \
-framework Cocoa \
-framework MultitouchSupport \
*.cpp


The header file is defined like this:

#ifndef TOUCH_H
#define TOUCH_H

#include <mach/mach.h>
#include <IOKit/IOKitLib.h>
#include <CoreFoundation/CoreFoundation.h>

#include <map>
#include <vector>
#include <iostream>

extern TouchPadState touchPadState;

extern "C" {

typedef struct { float x,y; } mtPoint;
typedef struct { mtPoint pos,vel; } mtReadout;

typedef struct {
int frame;
double timestamp;
int identifier, state, foo3, foo4;
mtReadout normalized;
float size;
int zero1;
float angle, majorAxis, minorAxis; // ellipsoid
mtReadout mm;
int zero2[2];
float unk2;
} Finger;

typedef long MTDeviceRef;
typedef int (*MTContactCallbackFunction)(int,Finger*,int,double,int);

MTDeviceRef MTDeviceCreateDefault();
void MTRegisterContactFrameCallback(MTDeviceRef, MTContactCallbackFunction);
void MTUnregisterContactFrameCallback(MTDeviceRef, MTContactCallbackFunction);
void MTDeviceStart(MTDeviceRef, int);
void MTDeviceStop(MTDeviceRef);
void MTDeviceRelease(MTDeviceRef);
}

extern MTDeviceRef mtDevice;

extern void touchDeviceStart();
extern void touchDeviceStop();

#endif


The implementation is as follows:

#include <stdio.h>
#include "touch.h"

MTDeviceRef mtDevice;

int touchDeviceCallback(int device, Finger *data, int nFingers, double timestamp, int frame) {
for (int i=0; i Finger *f = &data[i];
printf("Frame %7d: Angle %6.2f, ellipse %6.3f x%6.3f; "
"position (%6.3f,%6.3f) vel (%6.3f,%6.3f) "
"ID %d, state %d [%d %d?] size %6.3f, %6.3f?\n",
f->frame,
f->angle * 90 / atan2(1,0),
f->majorAxis,
f->minorAxis,
f->normalized.pos.x,
f->normalized.pos.y,
f->normalized.vel.x,
f->normalized.vel.y,
f->identifier, f->state,
f->foo3,
f->foo4,
f->size,
f->unk2);
}
return 0;
}

void touchDeviceStart() {
printf("Starting touch device...\n");
mtDevice = MTDeviceCreateDefault();
MTRegisterContactFrameCallback(mtDevice, touchDeviceCallback);
MTDeviceStart(mtDevice, 0);
}

void touchDeviceStop() {
printf("Stopping touch device...\n");
MTDeviceStop(mtDevice);
MTUnregisterContactFrameCallback(mtDevice, touchDeviceCallback);
MTDeviceRelease(mtDevice);
}


Hope it's useful!