Skip to content

Commit

Permalink
feat: add support for mouse clicks with modifier keys
Browse files Browse the repository at this point in the history
  • Loading branch information
socsieng committed Jan 1, 2021
1 parent 21bf513 commit 1654fd7
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 15 deletions.
4 changes: 3 additions & 1 deletion Sources/SendKeysLib/Commands/CommandExecutor.swift
Expand Up @@ -57,11 +57,13 @@ public class CommandExecutor: CommandExecutorProtocol {

private func executeMouseClick(_ command: Command) {
let button = command.arguments[0]!
let clicks = Int(command.arguments[1]!)!
let modifiers = command.arguments[1] ?? ""
let clicks = Int(command.arguments[2]!)!

try! mouseController.click(
CGPoint(x: -1, y: -1),
button: getMouseButton(button: button),
flags: KeyPresser.getModifierFlags(modifiers.components(separatedBy: ",")),
clickCount: clicks
)
}
Expand Down
6 changes: 4 additions & 2 deletions Sources/SendKeysLib/Commands/MouseClickCommandMatcher.swift
Expand Up @@ -2,15 +2,17 @@ import Foundation

public class MouseClickCommandMatcher: CommandMatcher {
public init() {
super.init(try! NSRegularExpression(pattern: "\\<m:([a-z]+)(:(\\d+))?\\>"))
super.init(try! NSRegularExpression(pattern: "\\<m:([a-z]+)(:([a-z,]+))?(:(\\d+))?\\>"))
}

override public func createCommand(_ arguments: [String?]) -> Command {
let button = arguments[1]
let clicks = arguments[3]
let modifiers = arguments[3]
let clicks = arguments[5]

return Command(.mouseClick, [
button!,
modifiers,
clicks ?? "1"
])
}
Expand Down
21 changes: 13 additions & 8 deletions Sources/SendKeysLib/KeyPresser.swift
Expand Up @@ -3,13 +3,7 @@ import Foundation
class KeyPresser {
func pressKey(key: String, modifiers: [String]) throws {
let keycode = KeyCodes.getKeyCode(key) ?? 0

var flags: CGEventFlags = []
for modifier in modifiers {
let flag = try getModifierFlag(modifier)
flags.insert(flag)
}

let flags = try! KeyPresser.getModifierFlags(modifiers)
let keyDownEvent = CGEvent(keyboardEventSource: nil, virtualKey: keycode, keyDown: true)

if keycode == 0 {
Expand All @@ -29,7 +23,18 @@ class KeyPresser {
keyUpEvent!.post(tap: CGEventTapLocation.cghidEventTap)
}

private func getModifierFlag(_ modifier: String) throws -> CGEventFlags {
static func getModifierFlags(_ modifiers: [String]) throws -> CGEventFlags {
var flags: CGEventFlags = []

for modifier in modifiers.filter({ !$0.isEmpty }) {
let flag = try getModifierFlag(modifier)
flags.insert(flag)
}

return flags
}

private static func getModifierFlag(_ modifier: String) throws -> CGEventFlags {
switch modifier {
case "",
"cmd",
Expand Down
3 changes: 2 additions & 1 deletion Sources/SendKeysLib/MouseController.swift
Expand Up @@ -22,7 +22,7 @@ class MouseController {
animator.animate()
}

func click(_ location: CGPoint, button: CGMouseButton, clickCount: Int) {
func click(_ location: CGPoint, button: CGMouseButton, flags: CGEventFlags, clickCount: Int) {
let resolvedLocation = resolveLocation(location)

var downMouseType = CGEventType.leftMouseDown
Expand All @@ -34,6 +34,7 @@ class MouseController {
}

let downEvent = CGEvent(mouseEventSource: nil, mouseType: downMouseType, mouseCursorPosition: resolvedLocation, mouseButton: button)
downEvent?.flags = flags
downEvent?.post(tap: CGEventTapLocation.cghidEventTap)

let upEvent = CGEvent(mouseEventSource: nil, mouseType: upMouseType, mouseCursorPosition: resolvedLocation, mouseButton: button)
Expand Down
22 changes: 20 additions & 2 deletions Tests/SendKeysTests/CommandIteratorTests.swift
Expand Up @@ -141,7 +141,16 @@ final class CommandIteratorTests: XCTestCase {
XCTAssertEqual(
commands,
[
Command(CommandType.mouseClick, ["left", "1"])
Command(CommandType.mouseClick, ["left", nil, "1"])
])
}

func testParsesMouseClickWithModifiers() throws {
let commands = getCommands(CommandsIterator("<m:left:shift,command>"))
XCTAssertEqual(
commands,
[
Command(CommandType.mouseClick, ["left", "shift,command", "1"])
])
}

Expand All @@ -150,7 +159,16 @@ final class CommandIteratorTests: XCTestCase {
XCTAssertEqual(
commands,
[
Command(CommandType.mouseClick, ["right", "2"])
Command(CommandType.mouseClick, ["right", nil, "2"])
])
}

func testParsesMouseClickWithModifiersAndClickCount() throws {
let commands = getCommands(CommandsIterator("<m:right:command:2>"))
XCTAssertEqual(
commands,
[
Command(CommandType.mouseClick, ["right", "command", "2"])
])
}

Expand Down
2 changes: 1 addition & 1 deletion Tests/SendKeysTests/CommandsProcessorTests.swift
Expand Up @@ -130,7 +130,7 @@ final class CommandProcessorTests: XCTestCase {
Command(.pause, ["0.1"]),
Command(.mouseMove, ["-1", "-1", "200", "200", "1"]),
Command(.pause, ["0.1"]),
Command(.mouseClick, ["left", "1"]),
Command(.mouseClick, ["left", nil, "1"]),
])
}
}

0 comments on commit 1654fd7

Please sign in to comment.