diff --git a/Sources/SendKeysLib/Commands/Command.swift b/Sources/SendKeysLib/Commands/Command.swift index 7db2fb1..ac0a252 100644 --- a/Sources/SendKeysLib/Commands/Command.swift +++ b/Sources/SendKeysLib/Commands/Command.swift @@ -23,6 +23,14 @@ public protocol CommandProtocol { func equals(_ comparison: Command) -> Bool } +protocol RequiresKeyPresser { + var keyPresser: KeyPresser? { get set } +} + +protocol RequiresMouseController { + var mouseController: MouseController? { get set } +} + public class Command: Equatable, CustomStringConvertible { public class var commandType: CommandType { return .undefined } diff --git a/Sources/SendKeysLib/Commands/CommandFactory.swift b/Sources/SendKeysLib/Commands/CommandFactory.swift index 321bb3e..b6cb800 100644 --- a/Sources/SendKeysLib/Commands/CommandFactory.swift +++ b/Sources/SendKeysLib/Commands/CommandFactory.swift @@ -14,7 +14,29 @@ public class CommandFactory { DefaultCommand.self ] - public static func create(_ commandType: Command.Type, arguments: [String?]) -> Command { - return commandType.init(arguments: arguments) + let keyPresser: KeyPresser + let mouseController: MouseController + + init(keyPresser: KeyPresser, mouseController: MouseController) { + self.keyPresser = keyPresser + self.mouseController = mouseController + } + + convenience public init() { + self.init(keyPresser: KeyPresser(), mouseController: MouseController(animationRefreshInterval: 0.01)) + } + + public func create(_ commandType: Command.Type, arguments: [String?]) -> Command { + let command = commandType.init(arguments: arguments) + + if var keyCommand = command as? RequiresKeyPresser { + keyCommand.keyPresser = keyPresser + } + + if var mouseCommand = command as? RequiresMouseController { + mouseCommand.mouseController = mouseController + } + + return command } } diff --git a/Sources/SendKeysLib/Commands/CommandsIterator.swift b/Sources/SendKeysLib/Commands/CommandsIterator.swift index 6c5f0d2..7b5e6b2 100644 --- a/Sources/SendKeysLib/Commands/CommandsIterator.swift +++ b/Sources/SendKeysLib/Commands/CommandsIterator.swift @@ -4,10 +4,13 @@ public class CommandsIterator: IteratorProtocol { public typealias Element = Command let commandString: String + let commandFactory: CommandFactory + var index = 0; - public init(_ commandString: String) { + public init(_ commandString: String, commandFactory: CommandFactory = CommandFactory()) { self.commandString = commandString + self.commandFactory = commandFactory } public func next() -> Element? { @@ -20,7 +23,7 @@ public class CommandsIterator: IteratorProtocol { } ) { let args = getArguments(commandString, matchResult!) - let command = CommandFactory.create(commandType, arguments: args) + let command = commandFactory.create(commandType, arguments: args) if matchResult != nil { let range = Range(matchResult!.range, in: commandString) diff --git a/Sources/SendKeysLib/Commands/CommandsProcessor.swift b/Sources/SendKeysLib/Commands/CommandsProcessor.swift index e85ee32..9125851 100644 --- a/Sources/SendKeysLib/Commands/CommandsProcessor.swift +++ b/Sources/SendKeysLib/Commands/CommandsProcessor.swift @@ -5,22 +5,31 @@ public class CommandsProcessor { let numberFormatter = NumberFormatter() let commandExecutor: CommandExecutorProtocol + let keyPresser: KeyPresser + let mouseController: MouseController - public init(defaultPause: Double, commandExecutor: CommandExecutorProtocol? = nil) { + init(defaultPause: Double, keyPresser: KeyPresser, mouseController: MouseController, commandExecutor: CommandExecutorProtocol? = nil) { self.defaultPause = defaultPause self.commandExecutor = commandExecutor ?? CommandExecutor() + self.keyPresser = keyPresser + self.mouseController = mouseController numberFormatter.usesSignificantDigits = true numberFormatter.minimumSignificantDigits = 1 numberFormatter.maximumSignificantDigits = 3 } + + convenience public init(defaultPause: Double, commandExecutor: CommandExecutorProtocol? = nil) { + self.init(defaultPause: defaultPause, keyPresser: KeyPresser(), mouseController: MouseController(animationRefreshInterval: 0.01), commandExecutor: commandExecutor) + } private func getDefaultPauseCommand() -> Command { return PauseCommand(duration: defaultPause) } public func process(_ commandString: String) { - let commands = IteratorSequence(CommandsIterator(commandString)) + let commandFactory = CommandFactory(keyPresser: keyPresser, mouseController: mouseController) + let commands = IteratorSequence(CommandsIterator(commandString, commandFactory: commandFactory)) var shouldDefaultPause = false var shouldIgnoreNextCommand = false diff --git a/Sources/SendKeysLib/Commands/KeyDownCommand.swift b/Sources/SendKeysLib/Commands/KeyDownCommand.swift index 0b34b87..62fdd18 100644 --- a/Sources/SendKeysLib/Commands/KeyDownCommand.swift +++ b/Sources/SendKeysLib/Commands/KeyDownCommand.swift @@ -15,6 +15,6 @@ public class KeyDownCommand: KeyPressCommand { } public override func execute() throws { - let _ = try! keyPresser.keyDown(key: key!, modifiers: modifiers) + let _ = try! keyPresser!.keyDown(key: key!, modifiers: modifiers) } } diff --git a/Sources/SendKeysLib/Commands/KeyPressCommand.swift b/Sources/SendKeysLib/Commands/KeyPressCommand.swift index 6fc99f0..bd54214 100644 --- a/Sources/SendKeysLib/Commands/KeyPressCommand.swift +++ b/Sources/SendKeysLib/Commands/KeyPressCommand.swift @@ -1,6 +1,6 @@ import Foundation -public class KeyPressCommand: Command { +public class KeyPressCommand: Command, RequiresKeyPresser { public override class var commandType: CommandType { return .keyPress } private static let _expression = try! NSRegularExpression(pattern: "\\<[ck]:(.|[\\w]+)(:([,\\w⌘^⌥⇧]+))?\\>") @@ -9,7 +9,7 @@ public class KeyPressCommand: Command { var key: String? var modifiers: [String] = [] - let keyPresser = KeyPresser() + var keyPresser: KeyPresser? override init() { super.init() @@ -30,7 +30,7 @@ public class KeyPressCommand: Command { } public override func execute() throws { - try! keyPresser.keyPress(key: key!, modifiers: modifiers) + try! keyPresser!.keyPress(key: key!, modifiers: modifiers) } public override func equals(_ comparison: Command) -> Bool { diff --git a/Sources/SendKeysLib/Commands/KeyUpCommand.swift b/Sources/SendKeysLib/Commands/KeyUpCommand.swift index c3bfc0d..2d3734b 100644 --- a/Sources/SendKeysLib/Commands/KeyUpCommand.swift +++ b/Sources/SendKeysLib/Commands/KeyUpCommand.swift @@ -15,6 +15,6 @@ public class KeyUpCommand: KeyPressCommand { } public override func execute() throws { - let _ = try! keyPresser.keyUp(key: key!, modifiers: modifiers) + let _ = try! keyPresser!.keyUp(key: key!, modifiers: modifiers) } } diff --git a/Sources/SendKeysLib/Commands/MouseClickCommand.swift b/Sources/SendKeysLib/Commands/MouseClickCommand.swift index 1a6b5e3..df1053d 100644 --- a/Sources/SendKeysLib/Commands/MouseClickCommand.swift +++ b/Sources/SendKeysLib/Commands/MouseClickCommand.swift @@ -1,6 +1,6 @@ import Foundation -public class MouseClickCommand: Command { +public class MouseClickCommand: Command, RequiresMouseController { public override class var commandType: CommandType { return .mouseClick } private static let _expression = try! NSRegularExpression(pattern: "\\") @@ -10,7 +10,7 @@ public class MouseClickCommand: Command { var modifiers: [String] = [] var clicks: Int = 1 - let mouseController = MouseController() + var mouseController: MouseController? override init() { super.init() @@ -33,7 +33,7 @@ public class MouseClickCommand: Command { } public override func execute() throws { - try! mouseController.click( + try! mouseController!.click( nil, button: getMouseButton(button: button!), flags: try! KeyPresser.getModifierFlags(modifiers), diff --git a/Sources/SendKeysLib/Commands/MouseDragCommand.swift b/Sources/SendKeysLib/Commands/MouseDragCommand.swift index dac9d02..7b2173c 100644 --- a/Sources/SendKeysLib/Commands/MouseDragCommand.swift +++ b/Sources/SendKeysLib/Commands/MouseDragCommand.swift @@ -34,7 +34,7 @@ public class MouseDragCommand: MouseMoveCommand { } public override func execute() throws { - try! mouseController.drag( + try! mouseController!.drag( start: x1 == nil || y1 == nil ? nil : CGPoint(x: x1!, y: y1!), end: CGPoint(x: x2, y: y2), duration: duration, diff --git a/Sources/SendKeysLib/Commands/MouseMoveCommand.swift b/Sources/SendKeysLib/Commands/MouseMoveCommand.swift index aa97355..db4e700 100644 --- a/Sources/SendKeysLib/Commands/MouseMoveCommand.swift +++ b/Sources/SendKeysLib/Commands/MouseMoveCommand.swift @@ -38,7 +38,7 @@ public class MouseMoveCommand: MouseClickCommand { } public override func execute() throws { - mouseController.move( + mouseController!.move( start: x1 == nil || y1 == nil ? nil : CGPoint(x: x1!, y: y1!), end: CGPoint(x: x2, y: y2), duration: duration, diff --git a/Sources/SendKeysLib/Commands/MouseScrollCommand.swift b/Sources/SendKeysLib/Commands/MouseScrollCommand.swift index 3bf5e30..5fa9551 100644 --- a/Sources/SendKeysLib/Commands/MouseScrollCommand.swift +++ b/Sources/SendKeysLib/Commands/MouseScrollCommand.swift @@ -29,7 +29,7 @@ public class MouseScrollCommand: MouseClickCommand { } public override func execute() throws { - mouseController.scroll( + mouseController!.scroll( CGPoint(x: x, y: y), duration, flags: try! KeyPresser.getModifierFlags(modifiers) diff --git a/Sources/SendKeysLib/MouseController.swift b/Sources/SendKeysLib/MouseController.swift index d0eacc8..614de71 100644 --- a/Sources/SendKeysLib/MouseController.swift +++ b/Sources/SendKeysLib/MouseController.swift @@ -6,9 +6,13 @@ class MouseController { case vertical } - let animationRefreshInterval: TimeInterval = 0.01 + let animationRefreshInterval: TimeInterval let keyPresser = KeyPresser() + init(animationRefreshInterval: TimeInterval) { + self.animationRefreshInterval = animationRefreshInterval + } + func move(start: CGPoint?, end: CGPoint, duration: TimeInterval, flags: CGEventFlags) { let resolvedStart = start ?? getLocation()! let eventSource = CGEventSource(event: nil) diff --git a/Sources/SendKeysLib/MousePosition.swift b/Sources/SendKeysLib/MousePosition.swift index 34fda42..7d79c55 100644 --- a/Sources/SendKeysLib/MousePosition.swift +++ b/Sources/SendKeysLib/MousePosition.swift @@ -31,7 +31,7 @@ class MousePosition: ParsableCommand { } func printMousePosition() { - let location = MouseController().getLocation()! + let location = MouseController(animationRefreshInterval: 0.01).getLocation()! print(String(format: "%.0f,%.0f", location.x, location.y)) } diff --git a/Sources/SendKeysLib/Sender.swift b/Sources/SendKeysLib/Sender.swift index 7babe71..3162153 100644 --- a/Sources/SendKeysLib/Sender.swift +++ b/Sources/SendKeysLib/Sender.swift @@ -23,6 +23,9 @@ public struct Sender: ParsableCommand { @Option(name: .shortAndLong, help: "String of characters to send.") var characters: String? + @Option(help: "Number of seconds between animation updates.") + var animationInterval: Double = 0.01 + public init() { } public mutating func run() throws { @@ -32,7 +35,9 @@ public struct Sender: ParsableCommand { fputs("WARNING: Accessibility preferences must be enabled to use this tool. If running from the terminal, make sure that your terminal app has accessibility permissiions enabled.\n\n", stderr) } - let commandProcessor = CommandsProcessor(defaultPause: delay) + let keyPresser = KeyPresser() + let mouseController = MouseController(animationRefreshInterval: animationInterval) + let commandProcessor = CommandsProcessor(defaultPause: delay, keyPresser: keyPresser, mouseController: mouseController) var commandString: String? if !(inputFile ?? "").isEmpty {