@@ -44,6 +44,22 @@ import AppKit
4444/// - ``locateCenterOnScreen(_:grayscale:confidence:region:)``
4545/// - ``locateAllOnScreen(_:grayscale:confidence:region:)``
4646public class SwiftAutoGUI {
47+
48+ /// Represents mouse buttons that can be clicked.
49+ public enum MouseButton {
50+ case left
51+ case right
52+
53+ /// Maps to the corresponding CGMouseButton value
54+ var cgMouseButton : CGMouseButton {
55+ switch self {
56+ case . left:
57+ return . left
58+ case . right:
59+ return . right
60+ }
61+ }
62+ }
4763
4864 // MARK: Key Event
4965
@@ -513,6 +529,174 @@ public class SwiftAutoGUI {
513529 )
514530 scrollEvent? . post ( tap: . cghidEventTap)
515531 }
532+
533+ /// Performs a double-click with the specified mouse button at the current cursor position.
534+ ///
535+ /// This method simulates a double-click operation, commonly used to open files,
536+ /// select words in text, or activate items.
537+ ///
538+ /// - Parameter button: The mouse button to click (default: .left)
539+ ///
540+ /// - Note: The timing between clicks is handled automatically to match system double-click speed.
541+ ///
542+ /// ## Example
543+ ///
544+ /// ```swift
545+ /// // Double-click at current position
546+ /// SwiftAutoGUI.doubleClick()
547+ ///
548+ /// // Double-click with right button
549+ /// SwiftAutoGUI.doubleClick(button: .right)
550+ /// ```
551+ public static func doubleClick( button: MouseButton = . left) {
552+ var mouseLoc = NSEvent . mouseLocation
553+ mouseLoc. y = NSHeight ( NSScreen . screens [ 0 ] . frame) - mouseLoc. y
554+ doubleClick ( at: mouseLoc, button: button)
555+ }
556+
557+ /// Performs a double-click with the specified mouse button at a given position.
558+ ///
559+ /// This method simulates a double-click operation at the specified coordinates,
560+ /// commonly used to open files, select words in text, or activate items.
561+ ///
562+ /// - Parameters:
563+ /// - at: The position to click in CGWindow coordinates (origin at top-left)
564+ /// - button: The mouse button to click (default: .left)
565+ ///
566+ /// - Note: The timing between clicks is handled automatically to match system double-click speed.
567+ ///
568+ /// ## Example
569+ ///
570+ /// ```swift
571+ /// // Double-click at specific position
572+ /// SwiftAutoGUI.doubleClick(at: CGPoint(x: 100, y: 200))
573+ ///
574+ /// // Double-click at button location
575+ /// let buttonPos = CGPoint(x: 150, y: 300)
576+ /// SwiftAutoGUI.doubleClick(at: buttonPos)
577+ ///
578+ /// // Select a word in text editor
579+ /// SwiftAutoGUI.move(to: wordPosition)
580+ /// SwiftAutoGUI.doubleClick()
581+ /// ```
582+ public static func doubleClick( at position: CGPoint , button: MouseButton = . left) {
583+ let source = CGEventSource ( stateID: . hidSystemState)
584+
585+ // Create mouse down and up events with click count set to 2
586+ let mouseDownType : CGEventType = button == . left ? . leftMouseDown : . rightMouseDown
587+ let mouseUpType : CGEventType = button == . left ? . leftMouseUp : . rightMouseUp
588+
589+ // First click
590+ let firstDown = CGEvent ( mouseEventSource: source, mouseType: mouseDownType,
591+ mouseCursorPosition: position, mouseButton: button. cgMouseButton)
592+ firstDown? . post ( tap: . cghidEventTap)
593+
594+ let firstUp = CGEvent ( mouseEventSource: source, mouseType: mouseUpType,
595+ mouseCursorPosition: position, mouseButton: button. cgMouseButton)
596+ firstUp? . post ( tap: . cghidEventTap)
597+
598+ // Second click with click count = 2
599+ let secondDown = CGEvent ( mouseEventSource: source, mouseType: mouseDownType,
600+ mouseCursorPosition: position, mouseButton: button. cgMouseButton)
601+ secondDown? . setIntegerValueField ( . mouseEventClickState, value: 2 )
602+ secondDown? . post ( tap: . cghidEventTap)
603+
604+ let secondUp = CGEvent ( mouseEventSource: source, mouseType: mouseUpType,
605+ mouseCursorPosition: position, mouseButton: button. cgMouseButton)
606+ secondUp? . setIntegerValueField ( . mouseEventClickState, value: 2 )
607+ secondUp? . post ( tap: . cghidEventTap)
608+
609+ Thread . sleep ( forTimeInterval: 0.01 )
610+ }
611+
612+ /// Performs a triple-click with the specified mouse button at the current cursor position.
613+ ///
614+ /// This method simulates a triple-click operation, commonly used to select entire
615+ /// lines or paragraphs of text.
616+ ///
617+ /// - Parameter button: The mouse button to click (default: .left)
618+ ///
619+ /// - Note: The timing between clicks is handled automatically to match system settings.
620+ ///
621+ /// ## Example
622+ ///
623+ /// ```swift
624+ /// // Triple-click at current position
625+ /// SwiftAutoGUI.tripleClick()
626+ ///
627+ /// // Triple-click with right button
628+ /// SwiftAutoGUI.tripleClick(button: .right)
629+ /// ```
630+ public static func tripleClick( button: MouseButton = . left) {
631+ var mouseLoc = NSEvent . mouseLocation
632+ mouseLoc. y = NSHeight ( NSScreen . screens [ 0 ] . frame) - mouseLoc. y
633+ tripleClick ( at: mouseLoc, button: button)
634+ }
635+
636+ /// Performs a triple-click with the specified mouse button at a given position.
637+ ///
638+ /// This method simulates a triple-click operation at the specified coordinates,
639+ /// commonly used to select entire lines or paragraphs of text.
640+ ///
641+ /// - Parameters:
642+ /// - at: The position to click in CGWindow coordinates (origin at top-left)
643+ /// - button: The mouse button to click (default: .left)
644+ ///
645+ /// - Note: The timing between clicks is handled automatically to match system settings.
646+ ///
647+ /// ## Example
648+ ///
649+ /// ```swift
650+ /// // Triple-click at specific position
651+ /// SwiftAutoGUI.tripleClick(at: CGPoint(x: 150, y: 300))
652+ ///
653+ /// // Select entire paragraph
654+ /// let paragraphPos = CGPoint(x: 200, y: 400)
655+ /// SwiftAutoGUI.tripleClick(at: paragraphPos)
656+ ///
657+ /// // Triple-click with right button
658+ /// SwiftAutoGUI.tripleClick(at: CGPoint(x: 100, y: 200), button: .right)
659+ /// ```
660+ public static func tripleClick( at position: CGPoint , button: MouseButton = . left) {
661+ let source = CGEventSource ( stateID: . hidSystemState)
662+
663+ // Create mouse down and up events
664+ let mouseDownType : CGEventType = button == . left ? . leftMouseDown : . rightMouseDown
665+ let mouseUpType : CGEventType = button == . left ? . leftMouseUp : . rightMouseUp
666+
667+ // First click
668+ let firstDown = CGEvent ( mouseEventSource: source, mouseType: mouseDownType,
669+ mouseCursorPosition: position, mouseButton: button. cgMouseButton)
670+ firstDown? . post ( tap: . cghidEventTap)
671+
672+ let firstUp = CGEvent ( mouseEventSource: source, mouseType: mouseUpType,
673+ mouseCursorPosition: position, mouseButton: button. cgMouseButton)
674+ firstUp? . post ( tap: . cghidEventTap)
675+
676+ // Second click with click count = 2
677+ let secondDown = CGEvent ( mouseEventSource: source, mouseType: mouseDownType,
678+ mouseCursorPosition: position, mouseButton: button. cgMouseButton)
679+ secondDown? . setIntegerValueField ( . mouseEventClickState, value: 2 )
680+ secondDown? . post ( tap: . cghidEventTap)
681+
682+ let secondUp = CGEvent ( mouseEventSource: source, mouseType: mouseUpType,
683+ mouseCursorPosition: position, mouseButton: button. cgMouseButton)
684+ secondUp? . setIntegerValueField ( . mouseEventClickState, value: 2 )
685+ secondUp? . post ( tap: . cghidEventTap)
686+
687+ // Third click with click count = 3
688+ let thirdDown = CGEvent ( mouseEventSource: source, mouseType: mouseDownType,
689+ mouseCursorPosition: position, mouseButton: button. cgMouseButton)
690+ thirdDown? . setIntegerValueField ( . mouseEventClickState, value: 3 )
691+ thirdDown? . post ( tap: . cghidEventTap)
692+
693+ let thirdUp = CGEvent ( mouseEventSource: source, mouseType: mouseUpType,
694+ mouseCursorPosition: position, mouseButton: button. cgMouseButton)
695+ thirdUp? . setIntegerValueField ( . mouseEventClickState, value: 3 )
696+ thirdUp? . post ( tap: . cghidEventTap)
697+
698+ Thread . sleep ( forTimeInterval: 0.01 )
699+ }
516700
517701 private static func leftClickDown( position: CGPoint ) {
518702 let source = CGEventSource ( stateID: CGEventSourceStateID . hidSystemState)
0 commit comments