-->

Use GSEvent to send touch event,but it's inval

2019-06-08 17:21发布

问题:

I code to send a touch event to my app by GSEvent,get mach_port_t by GSCopyPurpleSystemEventPort().

the sending function was launched after the ApplicationDidFinishLaunch:option have completed.the app is UIControlView app.

code as follow:

void handleMouseEventAtPoint(CGPoint point, int buttons)
{
    // NOTE: Must store button state for comparision, port for
    //       mouse dragging and button up
    static int buttons_;
    static mach_port_t port_;

    int diff = buttons_ ^ buttons;
    bool twas = ((buttons_ & 0x1) != 0);
    bool tis = ((buttons & 0x1) != 0);
    buttons_ = buttons;

    // Round point values to prevent subpixel coordinates
    point.x = roundf(point.x);
    point.y = roundf(point.y);

    // Check for mouse button events
    mach_port_t purple;

    if ((diff & 0x10) != 0) {
        // Simulate Headset button press
        struct GSEventRecord record;

        memset(&record, 0, sizeof(record));

        record.type = (buttons & 0x4) != 0 ?
        kGSEventHeadsetButtonDown :
        kGSEventHeadsetButtonUp;

        record.timestamp = GSCurrentEventTimestamp();
        FixRecord(&record);
        GSSendSystemEvent(&record);
    }

    if ((diff & buttonThree) != 0) {
        // Simulate Home button press
        struct GSEventRecord record;

        memset(&record, 0, sizeof(record));

        record.type = (buttons & buttonThree) != 0 ?
        kGSEventMenuButtonDown :
        kGSEventMenuButtonUp;

        record.timestamp = GSCurrentEventTimestamp();
        FixRecord(&record);
        GSSendSystemEvent(&record);
    }

    if ((diff & buttonTwo) != 0) 
    {
        // Simulate Sleep/Wake button press
        struct GSEventRecord record;

        memset(&record, 0, sizeof(record));

        record.type = (buttons & buttonTwo) != 0 ?
        kGSEventLockButtonDown :
        kGSEventLockButtonUp;

        record.timestamp = GSCurrentEventTimestamp();
        FixRecord(&record);
        GSSendSystemEvent(&record);
    }

    if (twas != tis || tis) {
        // Main (left button) state changed, or was dragged
        struct {
            struct GSEventRecord record;
            struct 
            {
                struct GSEventRecordInfo info;
                struct GSPathInfo path;
            } data;
        } event;

        memset(&event, 0, sizeof(event));

        event.record.type = kGSEventHand;
        event.record.windowLocation = point;
        event.record.timestamp = GSCurrentEventTimestamp();
        event.record.infoSize = sizeof(event.data);

        event.data.info.handInfo.type = twas == tis ?
        kGSHandInfoTypeTouchDragged :
        tis ?
        kGSHandInfoTypeTouchDown :
        kGSHandInfoTypeTouchUp;

        event.data.info.handInfo._0x44 = 0x1;
        event.data.info.handInfo._0x48 = tis ? 0x1 : 0x0;

        event.data.info.pathPositions = 1;

        event.data.path.pathIndex = 0x01;
        event.data.path.pathIdentity = 0x02;
        event.data.path.pathProximity = tis ? 0x03 : 0x00;
        event.data.path.pathLocation = event.record.windowLocation;

        if (twas != tis && tis) 
        {
            // Button down and was not down before
            port_ = 0;

            CAWindowServer *server;

            server = [CAWindowServer serverIfRunning];
            char svrptrstr [255];
            sprintf(svrptrstr, "%p", server);

            NSLog(@"One!");

            if (server = [CAWindowServer serverIfRunning]) 
                //if (true)
            {
                NSLog(@"Two!");
                //NSArray *displays([server displays]);
                NSArray *displays = [server displays];
                if (displays != nil && [displays count] != 0)
                {
                    NSLog(@"Three!");
                    //CAWindowServer *display;
                    if (CAWindowServerDisplay *display = [displays objectAtIndex:0])
                    {
                        NSLog(@"Four!");
                        port_ = [display clientPortAtPosition:point];
                    }
                }
            }

            if (port_ == 0) 
            {
                // Is SpringBoard
                if (purple == 0)
                {
                    purple = GSGetPurpleSystemEventPort();
                    port_ = purple;

                }
            }
        }

        FixRecord(&event.record);

        GSSendEvent(&event.record, port_);
        NSLog(@"Event sent!");
        //GSSendSystemEvent(&event.record);
        //GSSendEvent(&event.record, purple);
    }

    if (purple != 0 && PurpleAllocated)
    {
        mach_port_deallocate(mach_task_self(), purple);
        NSLog(@"Deallocated mach_port!");
    }
}

but the app launch on the jailbreak ipad2(iOS5.01),there is no any click result,if click event was done,the debug.log would be there.

who can tell me what i have miss?

回答1:

I've seen this code somewhere else (I think it was on an app that translated mouse clicks to iPhone/iPad taps). The problem here is not the code or the port, but the event structure you are sending. This is the GSevent structure for iOS 3.0, not for iOS 5.0. It has changed, not only in structure but in values and tags. I suggest receiving UIEvents, translating them into GSEvents and looking at their content.