LoginSignup
14
11

More than 3 years have passed since last update.

Swift:キー入力・マウスクリック・ドラッグ・座標移動・ホイール入力を強制的に発動させる

Last updated at Posted at 2018-08-01

はじめに

プロジェクト名.entitlementsApp SandBoxYesからNoに変更してください.
macOS Mojaveからなのか確認できていませんが,App SandBoxの有無に関わらず,環境設定のアクセシビリティの制御許可を与えないと動かないものがあるっぽいです.

本記事の手法はあくまでmacOS向けのものです.

キー入力

単キー入力

func keyDown(key: CGKeyCode) {
    let source = CGEventSource(stateID: CGEventSourceStateID.hidSystemState)
    let event = CGEvent(keyboardEventSource: source, virtualKey: key, keyDown: true)
    event?.post(tap: CGEventTapLocation.cghidEventTap)
}

func keyUp(key: CGKeyCode) {
    let source = CGEventSource(stateID: CGEventSourceStateID.hidSystemState)
    let event = CGEvent(keyboardEventSource: source, virtualKey: key, keyDown: false)
    event?.post(tap: CGEventTapLocation.cghidEventTap)
}

// 使用例
keyDown(key: 0x7E) // 0x7Eは↑キー
keyUp(key: 0x7E)

CGKeyCode(US配列)

key name code key name code
kVK_ANSI_A 0x00 kVK_ANSI_I 0x22
kVK_ANSI_S 0x01 kVK_ANSI_P 0x23
kVK_ANSI_D 0x02 kVK_ANSI_L 0x25
kVK_ANSI_F 0x03 kVK_ANSI_J 0x26
kVK_ANSI_H 0x04 kVK_ANSI_Quote 0x27
kVK_ANSI_G 0x05 kVK_ANSI_K 0x28
kVK_ANSI_Z 0x06 kVK_ANSI_Semicolon 0x29
kVK_ANSI_X 0x07 kVK_ANSI_Backslash 0x2A
kVK_ANSI_C 0x08 kVK_ANSI_Comma 0x2B
kVK_ANSI_V 0x09 kVK_ANSI_Slash 0x2C
kVK_ANSI_B 0x0B kVK_ANSI_N 0x2D
kVK_ANSI_Q 0x0C kVK_ANSI_M 0x2E
kVK_ANSI_W 0x0D kVK_ANSI_Period 0x2F
kVK_ANSI_E 0x0E kVK_ANSI_Grave 0x32
kVK_ANSI_R 0x0F kVK_ANSI_KeypadDecimal 0x41
kVK_ANSI_Y 0x10 kVK_ANSI_KeypadMultiply 0x43
kVK_ANSI_T 0x11 kVK_ANSI_KeypadPlus 0x45
kVK_ANSI_1 0x12 kVK_ANSI_KeypadClear 0x47
kVK_ANSI_2 0x13 kVK_ANSI_KeypadDivide 0x4B
kVK_ANSI_3 0x14 kVK_ANSI_KeypadEnter 0x4C
kVK_ANSI_4 0x15 kVK_ANSI_KeypadMinus 0x4E
kVK_ANSI_6 0x16 kVK_ANSI_KeypadEquals 0x51
kVK_ANSI_5 0x17 kVK_ANSI_Keypad0 0x52
kVK_ANSI_Equal 0x18 kVK_ANSI_Keypad1 0x53
kVK_ANSI_9 0x19 kVK_ANSI_Keypad2 0x54
kVK_ANSI_7 0x1A kVK_ANSI_Keypad3 0x55
kVK_ANSI_Minus 0x1B kVK_ANSI_Keypad4 0x56
kVK_ANSI_8 0x1C kVK_ANSI_Keypad5 0x57
kVK_ANSI_0 0x1D kVK_ANSI_Keypad6 0x58
kVK_ANSI_RightBracket 0x1E kVK_ANSI_Keypad7 0x59
kVK_ANSI_O 0x1F kVK_ANSI_Keypad8 0x5B
kVK_ANSI_U 0x20 kVK_ANSI_Keypad9 0x5C
kVK_ANSI_LeftBracket 0x21

修飾キーを付加したキー入力

func keyDown(key: CGKeyCode, with: CGEventFlags) {
    let source = CGEventSource(stateID: CGEventSourceStateID.hidSystemState)
    let event = CGEvent(keyboardEventSource: source, virtualKey: key, keyDown: true)
    event?.flags = with
    event?.post(tap: CGEventTapLocation.cghidEventTap)
}

func keyUp(key: CGKeyCode, with: CGEventFlags) {
    let source = CGEventSource(stateID: CGEventSourceStateID.hidSystemState)
    let event = CGEvent(keyboardEventSource: source, virtualKey: key, keyDown: false)
    event?.flags = with
    event?.post(tap: CGEventTapLocation.cghidEventTap)
}

// 使用例
// Control + A
keyDown(key: 0x00, with: CGEventFlags.maskControl)
keyUp(key: 0x00, with: CGEventFlags.maskControl)

// Shift + Control + A
keyDown(key: 0x00, with: CGEventFlags.maskShift.union(CGEventFlags.maskControl))
keyUp(key: 0x00, with: CGEventFlags.maskShift.union(CGEventFlags.maskControl))

よく使う修飾キー
Optionキー:CGEventFlags.maskAlternate
Shiftキー:CGEventFlags.maskShift
Commandキー:CGEventFlags.maskCommand
Controlキー:CGEventFlags.maskControl

マウスクリック&ドラッグ

func leftClickDown(position: CGPoint) {
    let source = CGEventSource(stateID: CGEventSourceStateID.hidSystemState)
    let event = CGEvent(mouseEventSource: source, mouseType: CGEventType.leftMouseDown, 
                        mouseCursorPosition: position, mouseButton: CGMouseButton.left)
    event?.post(tap: CGEventTapLocation.cghidEventTap)
}

func leftClickUp(position: CGPoint) {
    let source = CGEventSource(stateID: CGEventSourceStateID.hidSystemState)
    let event = CGEvent(mouseEventSource: source, mouseType: CGEventType.leftMouseUp, 
                        mouseCursorPosition: position, mouseButton: CGMouseButton.left)
    event?.post(tap: CGEventTapLocation.cghidEventTap)
}

func leftDragged(to: CGPoint, from: CGPoint) {
    leftClickDown(position: from)
    let source = CGEventSource(stateID: CGEventSourceStateID.hidSystemState)
    let event = CGEvent(mouseEventSource: source, mouseType: CGEventType.leftMouseDragged, 
                        mouseCursorPosition: to, mouseButton: CGMouseButton.left)
    event?.post(tap: CGEventTapLocation.cghidEventTap)
    leftClickUp(position: to)
}

// 使用例
// 現在のマウス座標にてクリックを行う
var location = NSEvent.mouseLocation
for screen in NSScreen.screens {
    if screen.frame.contains(location) {
        location = CGPoint(x: location.x, y: NSHeight(screen.frame) - location.y)
        break
    }
}
leftClickDown(position: location)
leftClickUp(position: location)

// 現在のマウス座標からx座標+200px, y座標+200pxの地点に向けてドラッグを行う
leftDragged(to: CGPoint(x: location.x + 200, y: location.y + 200), from: location)

マウス座標移動

func moveMouse(dx: CGFloat, dy: CGFloat) {
    var location = NSEvent.mouseLocation
    for screen in NSScreen.screens {
        if screen.frame.contains(location) {
            location = CGPoint(x: location.x, y: NSHeight(screen.frame) - location.y)
            location = CGPoint(x: location.x - dx, y: location.y + dy)
            CGDisplayMoveCursorToPoint(0, location)
            break
        }
    }
}

ホイール入力

func wheel(dx: Int32, dy: Int32) {
    appDelegate.toggleIgnore(flag: false)
    let source = CGEventSource(stateID: CGEventSourceStateID.hidSystemState)
    let event = CGEvent(scrollWheelEvent2Source: source, units: CGScrollEventUnit.pixel,
                        wheelCount: 25, wheel1: dy, wheel2: dx, wheel3: 0)
    event?.post(tap: CGEventTapLocation.cghidEventTap)
    appDelegate.toggleIgnore(flag: true)
}

wheelCountがどういうものなのかはよくわかっていません.

参考

Swiftでマウスとキーボードのイベント制御
Where can I find a list of Mac virtual key codes?

14
11
4

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
14
11