9

I am interested in simulating a mouse click event/keyboard stroke on Mac OS X without actually moving the mouse.

In Windows, it is possible to do this using messages:

win32: simulate a click without simulating mouse movement?

Is there an analog of this for Mac OS X? I am aware of Quartz Event Services, but it seems that that API would only restrict me to sending events to the current key window. Is this true? Is it possible to send keyboard/mouse events to non-key windows? I really just need to be able to send a keyboard command to another app.

Community
  • 1
  • 1
Dany Joumaa
  • 2,030
  • 6
  • 30
  • 45
  • possible duplicate of [Simulating mouse input programmatically in OS X](http://stackoverflow.com/questions/2734117/simulating-mouse-input-programmatically-in-os-x) – John Calsbeek Aug 25 '12 at 16:38
  • 1
    I could be wrong, but I believe your problem will mostly be that the application itself selects which window responds to an event. In other words, there won't be any OS-level API to do this. I would suggest trying to do this via AppleScript and the System Events suite—if you can do it that way, then you can do it programmatically. Otherwise, it may be quite difficult. – John Calsbeek Aug 25 '12 at 16:43
  • 1
    Have a look at CGEventPostToPSN – Raviprakash May 03 '13 at 09:03

3 Answers3

6

I know this is an old thread, but I wanted to post an answer just in case anybody stumbles upon this.

The two best ways to do this are actually completely platform independent. (Unless you feel like using C, which is unnecessarily verbose for this in my opinion, but if you want to use it see this answer)

1) The easiest way is to use javAuto. (Note: javAuto has moved here). It's pretty much a java program the can compile and run basic automation scripts cross platform. For simulating a mouse click you can use this command:

mouseClick(button, x, y);

For simulating a mouseClick without moving the mouse you can use this:

// get cursor coordinates
int cPos[] = cursorGetPos();

// mouse click at the coordinates you want
mouseClick("left", x, y);

// instantly move the mouse back
mouseMove(cPos[0], cPos[1]);

Since the mouseClick and mouseMove commands don't involve any interim mouse movements, a click will happen at (x, y) but the mouse won't move at all.

2) The next best way to do this is to use regular Java, which will involve a bit more code than the same process in javAuto.

import java.awt.*;
import java.awt.event.InputEvent;

public class example {
    public static void main(String[] args) {
        //get the current coordinates
        PointerInfo a = MouseInfo.getPointerInfo();
        Point b  = a.getLocation();
        int xOrig = (int)b.getX();
        int yOrig = (int)b.getY();

        try {
            //simulate a click at 10, 50
            Robot r = new Robot();
            r.mouseMove(10, 50);
            r.mousePress(InputEvent.BUTTON1_MASK); //press the left mouse button
            r.mouseRelease(InputEvent.BUTTON1_MASK); //release the left mouse button

            //move the mouse back to the original position
            r.mouseMove(xOrig, yOrig);
        } catch (Exception e) {
            System.out.println(e.toString());
        }
    }
}
Community
  • 1
  • 1
John Dorian
  • 1,884
  • 1
  • 19
  • 29
  • 1
    I'm not working on this project any more, but seriously, great find man! I'm sure this will help many others in the future :) – Dany Joumaa Feb 10 '14 at 22:50
  • @John Would you know how to use javAuto to determine if a click was performed? Also, can javAuto import? – thetypist Sep 20 '14 at 05:55
  • 1
    @thetypist It can definitely import, however I'm almost sure that there's no way to detect if a click is performed in java at all, since it runs on the JVM and isn't hooked into the OS. I think detecting a mouseclick is something that you would want to use C for and would have to be platform dependent. – John Dorian Sep 22 '14 at 00:58
  • 1
    Those JavAuto links are broken. It is now here: https://github.com/Javauto – Jayden Lawson Dec 09 '20 at 23:14
6

Here is a working C program to simulate N clicks at a coordinate (X,Y):

// Compile instructions:
//
// gcc -o click click.c -Wall -framework ApplicationServices

#include <ApplicationServices/ApplicationServices.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  int x = 0, y = 0, n = 1;
  float duration = 0.1;

  if (argc < 3) {
    printf("USAGE: click X Y [N] [DURATION]\n");
    exit(1);
  }

  x = atoi(argv[1]);
  y = atoi(argv[2]);

  if (argc >= 4) {
    n = atoi(argv[3]);
  }

  if (argc >= 5) {
    duration = atof(argv[4]);
  }

  CGEventRef click_down = CGEventCreateMouseEvent(
    NULL, kCGEventLeftMouseDown,
    CGPointMake(x, y),
    kCGMouseButtonLeft
  );

  CGEventRef click_up = CGEventCreateMouseEvent(
    NULL, kCGEventLeftMouseUp,
    CGPointMake(x, y),
    kCGMouseButtonLeft
  );

  // Now, execute these events with an interval to make them noticeable
  for (int i = 0; i < n; i++) {
    CGEventPost(kCGHIDEventTap, click_down);
    sleep(duration);
    CGEventPost(kCGHIDEventTap, click_up);
    sleep(duration);
  }

  // Release the events
  CFRelease(click_down);
  CFRelease(click_up);

  return 0;
}

Hosted at https://gist.github.com/Dorian/5ae010cd70f02adf2107

Dorian
  • 22,759
  • 8
  • 120
  • 116
0

You can do this with NSEvent, CGEvent, or Accessibility APIs. The trick is that first you will normally need to make the application you want to click activate first if it is not the front most application. Then, you're just clicking on a point in screen coordinates.

uchuugaka
  • 12,679
  • 6
  • 37
  • 55