Skip to content

Conversation

@PekingSpades
Copy link
Contributor

@PekingSpades PekingSpades commented Dec 31, 2025

Please provide Issues links to:

Provide test code:

package main

import (
	"fmt"
	"github.com/go-vgo/robotgo"
)

func main() {
	// Single click
	robotgo.Click()

	// Double click (existing API, unchanged)
	robotgo.Click("left", true)

	// Triple click to select entire line/paragraph (new)
	err := robotgo.MultiClickE("left", 3)
	if err != nil {
		fmt.Println("triple click error:", err)
	}

	// Quadruple click (new)
	err = robotgo.MultiClickE("left", 4)
	if err != nil {
		fmt.Println("quad click error:", err)
	}
}

Description

This PR adds support for multi-click (triple-click, quadruple-click, etc.) and refactors the mouse click implementation to reduce code redundancy.

Why multi-click is needed

  • Triple-click is essential for text selection in GUI automation:
    • On macOS, triple-click selects an entire line or paragraph (Apple Support)
    • Text editors like BBEdit use triple-click for line selection, TextEdit for paragraph selection (macOS text selection)
  • RPA use cases: Users have requested triple-click in other automation tools like Ui.Vision RPA for selecting entire text elements
  • Currently robotgo only supports single-click and double-click, limiting automation scenarios

Changes

New API:

  • MultiClickE(button string, clickCount int) error - Perform any number of clicks with error handling

C layer refactoring:

  • Added unified multiClickErr(button, clickCount) function
  • macOS: Uses native kCGMouseEventClickState API for accurate click count
  • Windows/X11: Performs sequential clicks with proper timing (200ms interval)
  • Removed redundant wrapper functions (toggleMouse, clickMouse, doubleClick, clickMouseErr, doubleClickErr)
  • Fixed macOS doubleClick button parameter bug (was hardcoded to kCGMouseButtonLeft)

Code reduction:

  • C functions: 7 → 2
  • Go error formatting functions: 2 → 1
  • Total lines reduced: ~55 → ~50

Backward Compatibility

All existing APIs (Click, ClickE, Toggle, etc.) remain unchanged.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added error-aware mouse click APIs with detailed, platform-specific error reporting
    • Introduced unified multi-click handling across all platforms
  • Improvements

    • Enhanced mouse operation reliability with improved error detection and consistent feedback
    • Refined click handling for better cross-platform consistency

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 31, 2025

📝 Walkthrough

Walkthrough

Mouse control API refactored to return error codes, replacing individual click/toggle functions with unified error-aware handlers. Go wrappers updated with new public error-returning APIs and internal calls adapted to use new C functions.

Changes

Cohort / File(s) Summary
C Header API Redesign
mouse/mouse_c.h
toggleMouse signature changed to toggleMouseErr returning int error codes; clickMouse and doubleClick removed entirely; new multiClickErr function added for generalized multi-click handling with per-platform error propagation and input validation.
Go Wrapper Implementation
robotgo.go
Four new public/internal functions added: MouseButtonString (enum-to-string mapper), ClickE (error-aware click API), MultiClickE (multi-click with error handling), and formatClickError (OS-specific error formatting); existing Click and Toggle functions refactored to use new C error-returning functions while maintaining backward-compatible signatures.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ClickE
    participant formatClickError
    participant multiClickErr as C.multiClickErr
    participant OS as OS Layer

    User->>ClickE: ClickE(args...)
    ClickE->>ClickE: Parse & validate arguments
    alt Valid single/double click
        ClickE->>multiClickErr: multiClickErr(button, clickCount)
        multiClickErr->>OS: Perform multi-click sequence
        OS-->>multiClickErr: Error code (0=success)
        multiClickErr-->>ClickE: Return error code
        ClickE->>formatClickError: formatClickError(code, button, clickCount)
        formatClickError-->>ClickE: Formatted error or nil
    else Invalid arguments
        ClickE->>formatClickError: formatClickError(-1, ...)
        formatClickError-->>ClickE: Validation error
    end
    ClickE-->>User: error (nil or detailed message)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 With clicks now wise and errors caught,
The mouse API's redesigned with thought,
Each press returns a code, so true—
From C to Go, the path runs through,
No silent fails, just clear returns! ✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: introducing MultiClickE and multi-click support with triple-click capability mentioned.
Description check ✅ Passed The description is comprehensive, addresses the template requirements, includes related issues, provides test code, explains rationale, and details implementation changes.
Docstring Coverage ✅ Passed Docstring coverage is 81.82% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
robotgo.go (1)

837-843: Toggle ignores error from toggleMouseErr.

The Toggle function now calls C.toggleMouseErr but discards its return value, always returning nil. This defeats the purpose of the error-returning C function and violates user expectations since Toggle has an error return type.

🔎 Proposed fix
 func Toggle(key ...interface{}) error {
 	var button C.MMMouseButton = C.LEFT_BUTTON
 	if len(key) > 0 {
 		button = CheckMouse(key[0].(string))
 	}

 	down := true
 	if len(key) > 1 && key[1].(string) == "up" {
 		down = false
 	}
-	C.toggleMouseErr(C.bool(down), button)
+	if code := C.toggleMouseErr(C.bool(down), button); code != 0 {
+		btnName := MouseButtonString(button)
+		return fmt.Errorf("toggle failed (%s, down=%v): code=%d", btnName, down, int(code))
+	}
 	if len(key) > 2 {
 		MilliSleep(MouseSleep)
 	}

 	return nil
 }
🧹 Nitpick comments (2)
mouse/mouse_c.h (1)

199-202: Consider returning an error for invalid clickCount.

Returning 0 for clickCount < 1 silently succeeds without performing any action. This could mask programming errors where the caller accidentally passes zero or a negative value. Consider returning an error code instead to make such issues visible.

🔎 Proposed change
 int multiClickErr(MMMouseButton button, int clickCount){
 	if (clickCount < 1) {
-		return 0;
+		return -1;  // Invalid argument
 	}
robotgo.go (1)

748-760: Minor: kCGErrorSuccess entry is unreachable.

Code 0 maps to "kCGErrorSuccess", but formatClickError is only called when code != 0. Consider removing the entry or keeping it for documentation purposes.

🔎 Proposed change
 	case "darwin":
 		cgErrors := map[int]string{
-			0:    "kCGErrorSuccess",
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5a38884 and be3319b.

📒 Files selected for processing (2)
  • mouse/mouse_c.h
  • robotgo.go
🧰 Additional context used
🧬 Code graph analysis (2)
mouse/mouse_c.h (3)
base/xdisplay_c.h (1)
  • XGetMainDisplay (18-48)
robotgo_win.go (1)
  • SendInput (39-41)
mouse/mouse.h (1)
  • LEFT_BUTTON (12-20)
robotgo.go (1)
keycode.go (4)
  • WheelDown (28-28)
  • WheelUp (29-29)
  • WheelLeft (30-30)
  • WheelRight (31-31)
🔇 Additional comments (6)
mouse/mouse_c.h (2)

159-196: LGTM!

The error-returning toggleMouseErr implementation correctly handles error cases across all platforms:

  • macOS properly checks for NULL event creation and releases resources before returning
  • X11 correctly interprets the Status return value from XTestFakeButtonEvent
  • Windows uses GetLastError() for detailed error information

227-244: Sequential click approach for X11/Windows is reasonable.

The 200ms inter-click delay should work for most system configurations. Note that this simulates multi-clicks through rapid sequential clicks rather than using a native multi-click event (unlike macOS's kCGMouseEventClickState). Applications that rely on the OS to track click counts may behave differently.

If users report inconsistent multi-click behavior on specific platforms, consider making the inter-click delay configurable or adjusting based on system settings.

robotgo.go (4)

510-526: LGTM!

Clean reverse mapping of CheckMouse with a sensible fallback for unknown button types.


685-689: LGTM!

The Click function now routes through multiClickErr, maintaining backward compatibility by ignoring the return value. Users who need error handling can use the new ClickE variant.


724-724: Verify: defer MilliSleep executes even on failure.

Using defer here means the sleep occurs regardless of whether the click succeeds or fails. This differs from the original Click behavior where MilliSleep is called at the end unconditionally, so it's consistent—but worth confirming this is intended for error paths.


777-793: LGTM!

Clean implementation that's consistent with ClickE. The public API is straightforward: MultiClickE(button string, clickCount int) error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant