1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Macの座標系

Last updated at Posted at 2025-08-18

スクリーン座標

Mac の スクリーン座標 は、メインディスプレイの左下が原点 (x:0, y:0) です。
他の OS では左上が原点でしょうから、macOS は独特です。

マルチディスプレイの構成

CGGetActiveDisplayListを使用すると ディスプレイの枚数を、
CGDisplayBoundsを使用すると ディスプレイの配置・サイズを得ることができます。

import AppKit
var displays = [CGDirectDisplayID](repeating: 0, count: 32)
var count = UInt32(0)
if CGGetActiveDisplayList(32, &displays, &count) != .success {
    print("failed to get display list")
}

for n in 0 ..< Int(count) {
    let displayID = displays[n]
    print("DisplayID: \(displayID)", CGDisplayBounds(displayID))
}
実行結果
DisplayID: 2 (0.0, 0.0, 2560.0, 1440.0)
DisplayID: 1 (-1440.0, -540.0, 1440.0, 2560.0)

上記の結果から、自分のディスプレイ環境は 下図の構成であることが分かります。

dsp3.png

なお、CGDisplayBounds(0)でメインディスプレイの情報を得ることができます。

マウスカーソルの現在位置

NSEvent.mouseLocationで、マウスカーソルの現在位置を取得することができます。

var lastPos = CGPoint.zero
while true {
    Thread.sleep(forTimeInterval: 0.1) //100ms
    let mousePos = NSEvent.mouseLocation
    if mousePos == lastPos { continue }
    lastPos = mousePos
    print(mousePos) //小数点以下をサプレスした方が見やすい
}

マルチディスプレイ構成の場合は、サブディスプレイの配置場所に従い、ディスプレイをまたがった座標位置となります。

  • マウスカーソルを メインディスプレイの左側にあるサブディスプレイに移動すると、X座標がマイナス値になる
  • マウスカーソルをメインディスプレイの下側にあるサブディスプレイに移動すると、Y座標がマイナス値になる

このように、マルチディスプレイ構成全体で一つの座標系となります。

マウスカーソルの移動

CGDisplayMoveCursorToPointを使用すると、任意の座標にマウスカーソルを移動することができます。
しかし、この API に指定する座標は 前項のスクリーン座標とは異なり、メインディスプレイの左上を原点とした座標系です。

例えば、前項のディスプレイ構成で、サブディスプレイの左上の スクリーン座標は (-1440, 1980) ですが、この API に指定する座標は (-1440, -570) となります。
同様に、サブディスプレイの左下の スクリーン座標は (-1440, -580) ですが、この API に指定する座標は (-1440, 2020) となります。

//サブディスプレイ左上 スクリーン座標 (-1440, 1980) 
CGDisplayMoveCursorToPoint(0, CGPoint(x: -1440, y: -570))

//サブディスプレイ左下 スクリーン座標 (-1440, -580)
CGDisplayMoveCursorToPoint(0, CGPoint(x: -1440, y: 2020))

毎度 座標を計算するのが面倒なので、スクリーン座標 で指定できる マウスカーソル移動関数を作成しました。

func mouseMove(screenCoordinate pos: CGPoint) {
    let mainDisplayBounds = CGDisplayBounds(0)
    let point = CGPoint(x: pos.x, y: mainDisplayBounds.height - pos.y)
    CGDisplayMoveCursorToPoint(0, point)
}

//サブディスプレイ左上 スクリーン座標 (-1440, 1980) 
mouseMove(screenCoordinate: CGPoint(x: -1440, y: 1980))

//サブディスプレイ左下 スクリーン座標 (-1440, -580)
mouseMove(screenCoordinate: CGPoint(x: -1440, y: -580))

iPhoneミラーリングを使用して iPhone の操作を Mac から自動化しようとしてハマったポイントでした。

画面タップ(マウスクリック)には 別な問題があり、iPhone の自動操作の壁は 高くて厚い です。これについては、別な記事で取り上げようと思います。

以上

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?