3

I need to send mouse click events to an arbitrary process (not necessarily the front one) without bringing that process's window to the front.

This code works for sending a mouse click and letting the window server send it to whatever process it decides has focus:

#include <ApplicationServices/ApplicationServices.h>

int
main()
{
    CGEventRef down, up;

    down = CGEventCreateMouseEvent(
        NULL,
        kCGEventLeftMouseDown,
        CGPointMake(16, 36),
        kCGMouseButtonLeft
    );
    up = CGEventCreateMouseEvent(
        NULL,
        kCGEventLeftMouseUp,
        CGPointMake(16, 36),
        kCGMouseButtonLeft
    );

    CGEventPost(kCGHIDEventTap, down);
    CGEventPost(kCGHIDEventTap, up);

    CFRelease(down);
    CFRelease(up);

    return 0;
}

I can send mouse click events via CGEventPost() just fine, but that requires the target process to have focus (which I am trying to avoid).

I can send keyboard events via CGEventPostToPSN() just fine, and as far as I can tell, mouse move events work too, what I'm having trouble with is mouse down/up events.

This code (pretty much the above, the only difference being that I specify myself which process to send the events to) does not work and I don't even know how to find out where it breaks down.

#include <ApplicationServices/ApplicationServices.h>
#include <Carbon/Carbon.h> /* for ProcessSerialNumber stuff */
#include <stdio.h>

int
main()
{
    ProcessSerialNumber psn;
    CGEventRef      down, up;

    if (GetFrontProcess(&psn) != noErr) {
        printf("Unable to get front process\n");
        return 1;
    }

    down = CGEventCreateMouseEvent(
        NULL,
        kCGEventLeftMouseDown,
        CGPointMake(16, 36),
        kCGMouseButtonLeft
    );
    up = CGEventCreateMouseEvent(
        NULL,
        kCGEventLeftMouseUp,
        CGPointMake(16, 36),
        kCGMouseButtonLeft
    );

    CGEventPostToPSN(&psn, down);
    CGEventPostToPSN(&psn, up);

    CFRelease(down);
    CFRelease(up);

    return 0;
}

I've been stuck on this for a few days now, and I can't seem to figure it out. According to the documentation this is (as far as I can tell) exactly how it is supposed to be done.

I have tested this code on Snow Leopard and Lion, with the same results.

Could somebody who has had success with clicking via CGEventPostToPSN() please shed some insight on the proper way to accomplish this?

user992364
  • 442
  • 3
  • 18
  • 1
    You can't send a mouse click event to a window that's covered by another window. Is that what you're trying to do? – Rob Keniger Mar 13 '12 at 22:56
  • @RobKeniger Yes, that is what I am trying to do... It's funny, because I CAN send keyboard events to stuff that's covered, and I seem to be able to send mouse move events to stuff that's covered, so why doesn't clicking work? The Apple documentation doesn't mention anything specifically about clicking to something in the background not being possible, so all evidence that I have leads to it being possible. I'm not trying to refuse your help, but to quote Wikipedia: [Citation Needed] – user992364 Mar 13 '12 at 23:53
  • @RobKeniger However, if there really is NO WAY whatsoever, what workaround do you suggest? Is there some way that the user wouldn't see the window on top for a brief moment while I'm doing what I need with it, and wouldn't prevent the user from sending more input while I do my stuff, and wouldn't leave the cursor in a different position than before I sent the event? – user992364 Mar 13 '12 at 23:54
  • I ran this code, with the position in the current window of the current application, it didn't click either. (on Mavericks) – sam boosalis Sep 25 '14 at 08:38
  • @user992364 did you ever figure this out? I have it working with a test HTML site, which draws where I click. But if I try it in a flash based app I'm trying to automate, it doesn't register. Even custom onMouseDown events don't fire. I don't get it, it works with just CGEventPost. – Tiago Apr 10 '17 at 20:23

0 Answers0