BlueM / cliclick

macOS CLI tool for emulating mouse and keyboard events
https://www.bluem.net
Other
1.59k stars 116 forks source link

Is it possible to emulate mouse clicks without application focus? #136

Closed leifericf closed 2 years ago

leifericf commented 2 years ago

I'm using cliclick to emulate mouse clicks in some applications. These applications are often running in the background, either behind other windows or minimized to the Dock. Before I can emulate mouse clicks in said applications, I must bring them to the foreground. I achieve this by using osascript -e 'activate application "AppName"'

This works well, however, it's annoying that the app pops up over other things I'm doing, and that the mouse cursor is moved. I can use the -r flag to restore the mouse cursor to its previous location, but I haven't been able to figure out how to leave the application running minimized or in the Dock, i.e., not bringing the application to the foreground.

My goal is to have the automation running completely in the background. For example by instantiating a separate, "virtual mouse cursor," which is independent from the mouse cursor I'm using manually to do other stuff.

Does cliclick offer the means to achieve this, possibly in combination with some other library?

BlueM commented 2 years ago

Cliclick doesn’t know anything about applications or windows, therefore this is not possible. And I’m not aware of a way to achieve this.

leifericf commented 2 years ago

Thanks for taking the time to respond, @BlueM! I thought that might be difficult to achieve.

cotfas commented 2 years ago

"And I’m not aware of a way to achieve this." You can do that.

Simulate CLICK:

static void doClickDown() {
    printfD("exec doClickDown\n");

    CGPoint mouseCursorPosition = getCurrentMousePossition();
    CGEventRef mouseDownEv = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, mouseCursorPosition, kCGMouseButtonLeft);
    CGEventPost(kCGHIDEventTap, mouseDownEv);
    CFRelease(mouseDownEv);
}

static void doClickUp() {
    printfD("exec doClickUp\n");

    CGPoint mouseCursorPosition = getCurrentMousePossition();

    CGEventRef mouseUpEv = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseUp, mouseCursorPosition, kCGMouseButtonLeft);
    CGEventPost (kCGHIDEventTap, mouseUpEv);
    CFRelease(mouseUpEv);
}

static void doClickDrag() {
    printfD("exec doClickDrag\n");

    CGPoint mouseCursorPosition = getCurrentMousePossition();

    CGEventRef mouseUpEv = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDragged, mouseCursorPosition, kCGMouseButtonLeft);
    CGEventPost (kCGHIDEventTap, mouseUpEv);
    CFRelease(mouseUpEv);
}

And you can use AXUIElementCopyAttributeValue to iterate between opened window .. More on: // source-code https://github.com/lwouis/alt-tab-macos/

cotfas commented 2 years ago
    func focusWindow() {
        AXUIElementPerformAction(self.elementRef, kAXRaiseAction as CFString)
    }

// source-code https://github.com/keith/ModMove

cotfas commented 2 years ago

I'm using cliclick to emulate mouse clicks in some applications. These applications are often running in the background, either behind other windows or minimized to the Dock. Before I can emulate mouse clicks in said applications, I must bring them to the foreground. I achieve this by using osascript -e 'activate application "AppName"'

This works well, however, it's annoying that the app pops up over other things I'm doing, and that the mouse cursor is moved. I can use the -r flag to restore the mouse cursor to its previous location, but I haven't been able to figure out how to leave the application running minimized or in the Dock, i.e., not bringing the application to the foreground.

My goal is to have the automation running completely in the background. For example by instantiating a separate, "virtual mouse cursor," which is independent from the mouse cursor I'm using manually to do other stuff.

Does cliclick offer the means to achieve this, possibly in combination with some other library?

Nice point! I am also interested in this if you manage to achieve (to have clicks when app is hidden/not visible)!

cotfas commented 2 years ago

Screenshot 2022-03-09 at 08 06 25

Here is my library with what I have so far on accessibility!

BlueM commented 2 years ago

@cotfas: this is pretty much what cliclick does: https://github.com/BlueM/cliclick/blob/master/Actions/ClickAction.m#L56

The question was if it is possible to emulate clicks in applications which may even be running minimized in the dock – emulating “normal” clicks doesn’t help in this situation. And a function called focusWindow() is surely not what @leifericf wanted when he asked if it would be possible to leave applications in the background.

leifericf commented 2 years ago

Indeed, I can already achieve this by using osascript to bring the desired window to the foreground and then using cliclick to emulate clicks. But that interrupts the other stuff I'm doing on the same machine. As @BlueM says, I was looking for a way to emulate clicks in the background, i.e., without focusing on the application window.