Indeed, the following works perfectly on MacOS 10.15.7.
func switchToAppAndClick(withWindow windowNumber: Int32) {
let options = CGWindowListOption(arrayLiteral: CGWindowListOption.excludeDesktopElements, CGWindowListOption.optionOnScreenOnly)
let windowListInfo = CGWindowListCopyWindowInfo(options, CGWindowID(0))
guard let infoList = windowListInfo as NSArray? as? [[String: AnyObject]] else { return }
if let window = infoList.first(where: { ($0["kCGWindowNumber"] as? Int32) == windowNumber}), let pid = window["kCGWindowOwnerPID"] as? Int32 {
let app = NSRunningApplication(processIdentifier: pid)
app?.activate(options: .activateIgnoringOtherApps)
let inWindowClickpoint = CGPoint(x: 100 , y:200) // a clickable point in the targeted window coords
print("creating eventMouseDown and Up events")
let source = CGEventSource.init(stateID: .hidSystemState)
let position = CGPoint(x: 75, y: 100)
let eventDown = CGEvent(mouseEventSource: source, mouseType: .leftMouseDown, mouseCursorPosition: position , mouseButton: .left)
let eventUp = CGEvent(mouseEventSource: source, mouseType: .leftMouseUp, mouseCursorPosition: position , mouseButton: .left)
print("posting \(eventUp)")
eventDown?.post(tap: .cghidEventTap)
Thread.sleep(forTimeInterval: 0.1)
print("posting \(eventDown)")
eventUp?.post(tap: .cghidEventTap)
}
}
@IBAction func tryToActivateWindow(_ sender: NSButton) {
print("begin -----------")
print(self.view.window?.windowNumber)
let mousePosition = NSPoint(x: 205,y: 200) // This corresponds to a visible window that's not part of this App
print("Mouse coordinates (\(mousePosition.x),\(mousePosition.y))")
let screenHeight = NSScreen.main!.frame.height
print("Screenheight: \(screenHeight)")
var screenPosition: NSPoint = mousePosition
screenPosition.y = screenHeight - mousePosition.y
print("Screen coordinates (\(screenPosition.x),\(screenPosition.y))")
let numberOfHitWindow = NSWindow.windowNumber(at: screenPosition, belowWindowWithWindowNumber: 0)
print("Window hit: \(numberOfHitWindow)")
CGDisplayMoveCursorToPoint(0, mousePosition) // Just for visual reference
switchToAppAndClick(withWindow: Int32(numberOfHitWindow))
}
So, I tried on BigSur 11.5.
I was asked to authorise accessibility control. What I did.
But then it does not work.
Hopefully, I found this:
https://stackoverflow.com/questions/65073294/is-it-possible-to-simulate-click-using-cgevent-for-ios-app-on-mac-with-m1
Which explains:
After the last Big Sur update this code works, but you need to focus window first time.
if(firstTime) testClick()
testClick()
So I adapted the code. No need to test for firstTime. And now, IT WORKS ! Strange, but it works:
func testClick() {
let source = CGEventSource.init(stateID: .hidSystemState)
let position = CGPoint(x: 75, y: 100)
let eventDown = CGEvent(mouseEventSource: source, mouseType: .leftMouseDown, mouseCursorPosition: position , mouseButton: .left)
let eventUp = CGEvent(mouseEventSource: source, mouseType: .leftMouseUp, mouseCursorPosition: position , mouseButton: .left)
print("posting \(eventUp)")
eventDown?.post(tap: .cghidEventTap)
Thread.sleep(forTimeInterval: 0.1)
print("posting \(eventDown)")
eventUp?.post(tap: .cghidEventTap)
}
func switchToAppAndClick(withWindow windowNumber: Int32) {
let options = CGWindowListOption(arrayLiteral: CGWindowListOption.excludeDesktopElements, CGWindowListOption.optionOnScreenOnly)
let windowListInfo = CGWindowListCopyWindowInfo(options, CGWindowID(0))
guard let infoList = windowListInfo as NSArray? as? [[String: AnyObject]] else { return }
if let window = infoList.first(where: { ($0["kCGWindowNumber"] as? Int32) == windowNumber}), let pid = window["kCGWindowOwnerPID"] as? Int32 {
let app = NSRunningApplication(processIdentifier: pid)
app?.activate(options: .activateIgnoringOtherApps)
let inWindowClickpoint = CGPoint(x: 100 , y:200) // a clickable point in the targeted window coords
print("creating eventMouseDown and Up events")
testClick()
testClick() // <----- CALL IT TWICE !!!!
}
}
@IBAction func tryToActivateWindow(_ sender: NSButton) {
print("begin -----------")
print(self.view.window?.windowNumber)
let mousePosition = NSPoint(x: 205,y: 200) // This corresponds to a visible window that's not part of this App
print("Mouse coordinates (\(mousePosition.x),\(mousePosition.y))")
let screenHeight = NSScreen.main!.frame.height
print("Screenheight: \(screenHeight)")
var screenPosition: NSPoint = mousePosition
screenPosition.y = screenHeight - mousePosition.y
print("Screen coordinates (\(screenPosition.x),\(screenPosition.y))")
let numberOfHitWindow = NSWindow.windowNumber(at: screenPosition, belowWindowWithWindowNumber: 0)
print("Window hit: \(numberOfHitWindow)")
CGDisplayMoveCursorToPoint(0, mousePosition) // Just for visual reference
switchToAppAndClick(withWindow: Int32(numberOfHitWindow))
}