8

I want to inject touch event in iPhone. I get the coordinates of touch event via network socket. GSSendEvent seems to be good choice. However, it needs GSEventRecord as one of the inputs.

Does anyone know how to prepare GSEventRecord? I prepared it based on some examples but the app crashes after GSSendEvent call.

Appreciate any help.

-(void) handleMouseEventAtPoint:(CGPoint) point
{
static mach_port_t port_;

// structure of touch GSEvent
struct GSTouchEvent {
    GSEventRecord record;
    GSHandInfo    handInfo;
} ;

struct GSTouchEvent *touchEvent = (struct GSTouchEvent *) malloc(sizeof(struct GSTouchEvent));

bzero(touchEvent, sizeof(touchEvent));

// set up GSEvent
touchEvent->record.type = kGSEventHand;
touchEvent->record.windowLocation = point;
touchEvent->record.timestamp = GSCurrentEventTimestamp();
touchEvent->record.infoSize = sizeof(GSHandInfo) + sizeof(GSPathInfo);
touchEvent->handInfo.type = getHandInfoType(0, 1);
touchEvent->handInfo.pathInfosCount = 1;
bzero(&touchEvent->handInfo.pathInfos[0], sizeof(GSPathInfo));
touchEvent->handInfo.pathInfos[0].pathIndex     = 1;
touchEvent->handInfo.pathInfos[0].pathIdentity  = 2;
touchEvent->handInfo.pathInfos[0].pathProximity = 1 ? 0x03 : 0x00;
touchEvent->handInfo.pathInfos[0].pathLocation  = point;

port_ = GSGetPurpleSystemEventPort();

GSSendEvent((GSEventRecord*)touchEvent ,port_);


}
static GSHandInfoType getHandInfoType(int touch_before, int touch_now){
if (!touch_before) {
    return (GSHandInfoType) kGSHandInfoType2TouchDown;
}
if (touch_now) {
    return (GSHandInfoType) kGSHandInfoType2TouchChange;
}
return (GSHandInfoType) kGSHandInfoType2TouchFinal;
}
TorukMakto
  • 1,936
  • 2
  • 21
  • 37

2 Answers2

6

Only tested on iOS 6

You are actually on the right track. The problem is you have to figure out what values you should assign to these variables.

First of all, you need to import GraphicsServices.h. Then, you can try the following code with the port which you can get from How to find the purple port for the front most application in IOS 5 and above?.

I am not an iOS expert and Apple doesn't provide any documentation so I can't explain much what's going on here. (It happens to work fine for me.)

Anyway, you can play with it using xcode debug mode to see what happens under the hood.

struct GSTouchEvent * touchEvent = (struct GSTouchEvent*) &gsTouchEvent;
bzero(touchEvent, sizeof(touchEvent));
touchEvent->record.type = kGSEventHand;
touchEvent->record.subtype = kGSEventSubTypeUnknown;
touchEvent->record.location = point;
touchEvent->record.windowLocation = point;
touchEvent->record.infoSize = sizeof(GSHandInfo) + sizeof(GSPathInfo);
touchEvent->record.timestamp = GSCurrentEventTimestamp();
touchEvent->record.window = winRef;
touchEvent->record.senderPID = 919;
bzero(&touchEvent->handInfo, sizeof(GSHandInfo));
bzero(&touchEvent->handInfo.pathInfos[0], sizeof(GSPathInfo));
GSHandInfo touchEventHandInfo;
touchEventHandInfo._0x5C = 0;
touchEventHandInfo.deltaX = 0;
touchEventHandInfo.deltaY = 0;
touchEventHandInfo.height = 0;
touchEventHandInfo.width = 0;
touchEvent->handInfo = touchEventHandInfo;
touchEvent->handInfo.type = handInfoType;
touchEvent->handInfo.deltaX = 1;
touchEvent->handInfo.deltaY = 1;
touchEvent->handInfo.pathInfosCount = 0;
touchEvent->handInfo.pathInfos[0].pathIndex = 1;
touchEvent->handInfo.pathInfos[0].pathIdentity = 2;
touchEvent->handInfo.pathInfos[0].pathProximity = (handInfoType == kGSHandInfoTypeTouchDown || handInfoType == kGSHandInfoTypeTouchDragged || handInfoType == kGSHandInfoTypeTouchMoved) ? 0x03: 0x00;
touchEvent->handInfo.x52 = 1;
touchEvent->handInfo.pathInfos[0].pathLocation = point;
touchEvent->handInfo.pathInfos[0].pathWindow = winRef;
GSEventRecord* record = (GSEventRecord*) touchEvent;
record->timestamp = GSCurrentEventTimestamp();
GSSendEvent(record, port);

To use this code, you have to call it multiple times. For one tap, there are touch-down, touch-drag and then touch-up.

Also note that pathProximity is 0 when touch is up.

As far as I remember, the winRef doesn't matter.

Hope this helps.

Edit: From Bugivore's comment, the problem is:

The way I allocated touchEvent via malloc was wrong. It should be done as EntryLevelDev showed - "static uint8_t handJob[sizeof(GSEventRecord) + sizeof(GSHandInfo) + sizeof(GSPathInfo)];"

Community
  • 1
  • 1
pt2121
  • 11,060
  • 7
  • 50
  • 68
  • Hi ELD - Thanks for the help. I tried and it crashes in objc_msgSend. – TorukMakto Apr 24 '13 at 04:28
  • alright, please check out my project on github...https://github.com/entryleveldev/touchy – pt2121 Apr 24 '13 at 04:40
  • Worked very well! Thank you much. – TorukMakto Apr 24 '13 at 06:53
  • 1
    The way I allocated touchEvent via malloc was wrong. It should be done as EntryLevelDev showed - "static uint8_t handJob[sizeof(GSEventRecord) + sizeof(GSHandInfo) + sizeof(GSPathInfo)];" – TorukMakto Apr 24 '13 at 10:52
  • But how can simulate multi touch event? – Suge Jul 08 '13 at 06:47
  • Yes, I can confirm that for iOS 6, this code works without the `winRef` values. Also, perhaps I just have an outdated version of `GSEvent.h`, but I found that I had to map the `kGSHandInfoTypeTouchDown` type to a value of `2`, and the `kGSHandInfoTypeTouchUp` type to `1`. Those were **not** the representations I had in my (old) GSEvent.h header. – Nate Jul 31 '13 at 09:20
  • I haven't tested yet. From what i've heard, it doesn't work on ios7. Sorry! – pt2121 Oct 09 '13 at 14:23
  • Does the Apple allows to publish a code with the implementation on App Store? – Brian Cannard Jan 08 '15 at 05:51
  • @avesus I don't think so. – pt2121 Jan 08 '15 at 15:42
3

Answer from EntryLevelDev is correct, but some of the value is not so important. I got the below codes from somewhere else and have done some try and errors, here is my codes(worked for till latested ios6).

And is anyone working on this for IOS7 now? I could not get it to work. see my post here:With GSCopyPurpleNamedPort(appId) in GraphicsServices deprecated in IOS7, what is the alternative approach?

static int prev_click = 0;

if (!click && !prev_click)
{
    //which should never enter
    NSLog(@"***error, postHandEvent cancel");
    return;
}

CGPoint location = CGPointMake(x, y);

struct GSTouchEvent {
    GSEventRecord record;
    GSHandInfo    handInfo;
} * event = (struct GSTouchEvent*) &touchEvent;
bzero(touchEvent, sizeof(touchEvent));

event->record.type = kGSEventHand;
event->record.windowLocation = location;
event->record.timestamp = GSCurrentEventTimestamp();
//NSLog(@"Timestamp GSCurrentEventTimestamp: %llu",GSCurrentEventTimestamp());
event->record.infoSize = sizeof(GSHandInfo) + sizeof(GSPathInfo);
event->handInfo.type = getHandInfoType(prev_click, click);

//must have the following line
event->handInfo.x52 = 1;

//below line is for ios4
//event->handInfo.pathInfosCount = 1;


bzero(&event->handInfo.pathInfos[0], sizeof(GSPathInfo));
event->handInfo.pathInfos[0].pathIndex     = 2;
//following 2 lines, they are by default
event->handInfo.pathInfos[0].pathMajorRadius = 1.0;
event->handInfo.pathInfos[0].pathPressure = 1.0;

//event->handInfo.pathInfos[0].pathIdentity  = 2;
event->handInfo.pathInfos[0].pathProximity = click ? 0x03 : 0x00;
//event->handInfo.pathInfos[0].pathProximity = action;
event->handInfo.pathInfos[0].pathLocation  = location;

// send GSEvent 
GSEventRecord *event1 = (GSEventRecord*) event;
sendGSEvent(event1);
Community
  • 1
  • 1
user2485972
  • 138
  • 1
  • 7
  • That's great. Good to know. Thx – pt2121 Jul 31 '13 at 13:52
  • 1
    No, not with Graphicsservices. We are using another way to simulate user touch tough. – user2485972 Oct 09 '13 at 14:35
  • 5
    Hi user2485972, can you share some info about your ios 7 touch injection? – huisinro Oct 12 '13 at 00:52
  • 1
    user2485972 want to answer http://stackoverflow.com/questions/19471572/inject-system-wide-touch-events-on-ios7 ? – Ben Dowling Oct 28 '13 at 17:19
  • Sorry guys, I am working for the enterprise. I cannot release the source. Only I can say it is similar to do with KIF framework(should be how it called, i have limit memory), but additionally need to deal with gesture recogniser. As is it possible for system wise touch on IOS7, the answer is no for me. – user2485972 Oct 30 '13 at 13:15
  • 1
    @user2485972 `As is it possible for system wise touch on IOS7, the answer is no for me` -- Are you saying you don't know of a way to simulate system wide touch event in iOS 7? – funroll Nov 07 '13 at 04:39