1

so I need to be able to move the mouse to any given point (x and y). I'm trying to do it with CGDisplayMoveCursor while it moves the cursors it does not place it where I expect it. I have two monitors in my set up. I get the frame via NSScreen.screens[i].frame and these are their frames.

Built-in Retina Display
NSRect (0.0, 0.0, 1440.0, 900.0)

SwitchResX4 - LG HDR WQHD
NSRect (-1186.0, 900.0, 3840.0, 1600.0)

Then when I receive the new point I use NSRect.contains(NSPoint) to find which of the two monitors contain that point. That part works as expected.

But then I want to move the cursor to that point but it doesn't work as you would expect (the cursor moves but not to the points as you would expect based on the frames). Here is the code for that.

let point = NSPoint(x: x, y: y)
guard let monitor = Monitor.displayIdWithPoint(point) else {
      SendlogCallbackEvent("D", "", "Found nil in monitor with point", #function, #file, #line)
 }      
 if CGDisplayMoveCursorToPoint(monitor.directDisplayId, point) == CGError.failure {
     SendlogCallbackEvent("D", "", "CGError.failer to move cursor", #function, #file, #line)
  }

I have read that it probably has to do with how CG and NS handle coordinate system in a different way but I haven't been able to figure how to make it work. How do I "convert" my NSPoint to a CGPoint so it works with CGDisplayMove... function. Or what is the best way to do this.

Gama
  • 352
  • 2
  • 16

1 Answers1

2

This snippet of your code:

let point = NSPoint(x: x, y: y)
guard let monitor = Monitor.displayIdWithPoint(point) else {
      SendlogCallbackEvent("D", "", "Found nil in monitor with point", #function, #file, #line)
}

gives me the impression that your point you're looking up is a point in the window system coordinate space (the coordinate space in which those two window frames are described).

But looking at the documentation of CGDisplayMoveCursorToPoint(_:_:), we see (emphasis mine):

point

The coordinates of a point in local display space. The origin is the upper-left corner of the specified display.

So I think you'll need to take your point, and transform it so that it's relative to the origin of your desired display:

let pointRelativeToScreen = point - monitor.frame.origin

if CGDisplayMoveCursorToPoint(monitor.directDisplayId, pointRelativeToScreen) == CGError.failure { ... }

Alternatively, there might be some other API which expects a cursor point in expressed in the window system's coordinates, which would automatically plop it onto the right screen for you. I don't have access to Xcode right now, so I can't check for this myself.

Alexander
  • 59,041
  • 12
  • 98
  • 151
  • yep that did the trick. I thought I read the documentation well but obviously I did not. Thank you. I also tried CGEvent to create a .mouseMove event but that seem to only work on the main screen? although I was pretty frustrated and I could have just not done right. – Gama May 18 '21 at 19:06