GSSendEvent - Inject Touch Event iOS

后端 未结 2 428
梦谈多话
梦谈多话 2020-12-05 16:35

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

相关标签:
2条回答
  • 2020-12-05 16:55

    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)];"

    0 讨论(0)
  • 2020-12-05 17:00

    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);
    
    0 讨论(0)
提交回复
热议问题