Перемещение курсора мыши с помощью CGDisplayMoveCursor не работает должным образом при перемещении между мониторами

#swift #macos #mouse

Вопрос:

поэтому мне нужно иметь возможность перемещать мышь в любую заданную точку (x и y). Я пытаюсь сделать это с помощью CGDisplayMoveCursor, пока он перемещает курсоры, он не помещает их туда, куда я ожидаю. У меня в настройках два монитора. Я получаю кадр через NSScreen.screens[i].кадр, и это их кадры.

 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)
 

Затем, когда я получаю новую точку, я использую NSRect.contains(NSPoint) ее, чтобы найти, какой из двух мониторов содержит эту точку. Эта часть работает так, как и ожидалось.

Но затем я хочу переместить курсор в эту точку, но это работает не так, как вы ожидали (курсор перемещается, но не в точки, как вы ожидали бы, основываясь на кадрах). Вот код для этого.

 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)
  }
 

Я читал, что это, вероятно, связано с тем, как CG и NS по-разному обрабатывают систему координат, но я не смог понять, как заставить ее работать. Как мне «преобразовать» свою точку NSPoint в точку CG, чтобы она работала с функцией CGDisplayMove…. Или как лучше всего это сделать.

Ответ №1:

Этот фрагмент вашего кода:

 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)
}
 

у меня создается впечатление, что point вы смотрите вверх-это точка в координатном пространстве оконной системы (координатное пространство, в котором описаны эти две оконные рамы).

Но , глядя на документацию CGDisplayMoveCursorToPoint(_:_:) , мы видим (курсив мой):

точка

Координаты точки в локальном пространстве отображения. Начало координат-это верхний левый угол указанного дисплея.

Поэтому я думаю , что вам нужно будет взять свой point и преобразовать его так, чтобы он был относительно источника желаемого отображения:

 let pointRelativeToScreen = point - monitor.frame.origin

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

В качестве альтернативы может существовать какой-либо другой API, который ожидает, что точка курсора будет выражена в координатах оконной системы, что автоматически выведет ее на нужный вам экран. У меня сейчас нет доступа к Xcode, поэтому я не могу проверить это сам.

Комментарии:

1. да, это сработало. Я думал, что хорошо прочитал документацию, но, очевидно, я этого не сделал. Спасибо. Я также попытался CGEvent создать событие .mouseMove, но, похоже, это работает только на главном экране? хотя я был довольно расстроен и мог просто поступить неправильно.